是否可以从Pack200创建的pack.gz文件中即时加载类(在内存中),而无需先将其解压缩到jar中?我能找到的所有示例都告诉我如何将其解压缩到.jar文件中,然后从.jar文件加载类。
答案 0 :(得分:0)
是的,这是可能的。 Pack200.Unpacker.unpack方法写入JarOutputStream;如果你在后台线程中这样做,你可以使用管道将新的JarOutputStream连接到JarInputStream,并从中读取。
public JarInputStream readPackFile(Path packGzFile)
throws IOException {
PipedInputStream pipeIn = new PipedInputStream();
PipedOutputStream pipeOut = new PipedOutputStream(pipeIn);
ExecutorService executor = Executors.newSingleThreadExecutor();
Callable<Void> unpacker = new Callable<Void>() {
@Override
public Void call()
throws IOException {
try (InputStream file =
new GZIPInputStream(
new BufferedInputStream(
Files.newInputStream(packGzFile)));
JarOutputStream jarOutput = new JarOutputStream(pipeOut)) {
Pack200.newUnpacker().unpack(file, jarOutput);
return null;
} finally {
executor.shutdown();
}
}
};
executor.submit(unpacker);
return new JarInputStream(pipeIn);
}
那应该就足够了。但是,仍有两个问题:
finish()
之前几乎肯定会关闭JarInputStream,导致finish()
由于管道损坏而生成IOException。要解决第一个问题,我们可以覆盖JarInputStream的close
方法来解决解包操作中的任何失败。要解决第二个问题,我们可以覆盖JarOutputStream中的finish()
来执行任何操作:
public JarInputStream readPackFile(Path packGzFile)
throws IOException {
PipedInputStream pipeIn = new PipedInputStream();
PipedOutputStream pipeOut = new PipedOutputStream(pipeIn);
class NonFinishingJarOutputStream
extends JarOutputStream {
NonFinishingJarOutputStream(OutputStream out)
throws IOException {
super(out);
}
@Override
public void finish()
throws IOException {
// Deliberately empty.
}
}
ExecutorService executor = Executors.newSingleThreadExecutor();
Callable<Void> unpacker = new Callable<Void>() {
@Override
public Void call()
throws IOException {
try (InputStream file =
new GZIPInputStream(
new BufferedInputStream(
Files.newInputStream(packGzFile)));
JarOutputStream jarOutput =
new NonFinishingJarOutputStream(pipeOut)) {
Pack200.newUnpacker().unpack(file, jarOutput);
return null;
} finally {
executor.shutdown();
}
}
};
Future<?> unpackerTask = executor.submit(unpacker);
return new JarInputStream(pipeIn) {
@Override
public void close()
throws IOException {
super.close();
try {
// If the unpack generated an exception, propagate it here.
unpackerTask.get();
} catch (ExecutionException e) {
throw new IOException(e);
} catch (InterruptedException e) {
InterruptedIOException iie = new InterruptedIOException();
iie.initCause(e);
throw iie;
}
}
};
}