使用 bytearray 加载 jar,找不到嵌套 类
Load jar using bytearray, cant find nested classes
想法
我在 byte[]
中有一个罐子 (postgresql-9.4.1208.jre7.jar
)。我想在 运行 时间内加载和连接以及 运行 一些基本的 SQL 命令。
实施
因此我创建了一个新的类加载器:
public class JarClassloader extends ClassLoader {
public interface DriverProblemReporter {
void reportDriverProblem(String name, Throwable e);
}
private final byte[] driverdata;
private final DriverProblemReporter problemReporter;
public JarClassloader(byte[] jar, String drivername, DriverProblemReporter reporter) {
super(ClassLoader.getSystemClassLoader());
this.problemReporter = reporter;
try {
JarInputStream jis = new JarInputStream(new ByteArrayInputStream(jar));
JarEntry entry = jis.getNextJarEntry();
while (entry != null) {
handleEntry(entry, jis);
entry = jis.getNextJarEntry();
}
} catch (IOException e) {
e.printStackTrace();
}
this.driverdata = jar;
}
private void handleEntry(JarEntry entry, JarInputStream jis) {
if (!entry.isDirectory()) {
ByteArrayOutputStream baos;
try {
baos = new ByteArrayOutputStream();
IOUtils.copy(jis, baos);
baos.flush();
} catch (IOException e) {
problemReporter.reportDriverProblem(entry.getName(), e);
return;
}
try {
defineClass(baos.toByteArray(), 0, baos.size());
} catch (LinkageError e) {
problemReporter.reportDriverProblem(entry.getName(), e);
}
}
}
}
Jar 加载成功,我可以获得驱动程序的实例。
景点
在连接到数据库的调用中我收到此错误:
java.lang.NoClassDefFoundError: org/postgresql/hostchooser/HostRequirement
at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:107)
at org.postgresql.core.ConnectionFactory.openConnection(ConnectionFactory.java:66)
at org.postgresql.jdbc.PgConnection.<init>(PgConnection.java:215)
at org.postgresql.Driver.makeConnection(Driver.java:406)
at org.postgresql.Driver.connect(Driver.java:274)
在堆栈跟踪中,我看到 org.postgresql.Driver
的工作实例正在寻找名为 org/postgresql/hostchooser/HostRequirement
的 class。
假设
我的 JarClassloader
不加载匿名嵌套 classes.
问题
我应该怎么做才能成功加载 jar 中的所有 classes?
您需要按照 classloader 需要它们的顺序加载 classes,而不是按照它们恰好在 JAR 文件中的顺序。因此,您需要重写 findClass()
方法并在此时搜索 JAR 文件以查找所请求的 class。
使用文件会简单很多
想法
我在 byte[]
中有一个罐子 (postgresql-9.4.1208.jre7.jar
)。我想在 运行 时间内加载和连接以及 运行 一些基本的 SQL 命令。
实施
因此我创建了一个新的类加载器:
public class JarClassloader extends ClassLoader {
public interface DriverProblemReporter {
void reportDriverProblem(String name, Throwable e);
}
private final byte[] driverdata;
private final DriverProblemReporter problemReporter;
public JarClassloader(byte[] jar, String drivername, DriverProblemReporter reporter) {
super(ClassLoader.getSystemClassLoader());
this.problemReporter = reporter;
try {
JarInputStream jis = new JarInputStream(new ByteArrayInputStream(jar));
JarEntry entry = jis.getNextJarEntry();
while (entry != null) {
handleEntry(entry, jis);
entry = jis.getNextJarEntry();
}
} catch (IOException e) {
e.printStackTrace();
}
this.driverdata = jar;
}
private void handleEntry(JarEntry entry, JarInputStream jis) {
if (!entry.isDirectory()) {
ByteArrayOutputStream baos;
try {
baos = new ByteArrayOutputStream();
IOUtils.copy(jis, baos);
baos.flush();
} catch (IOException e) {
problemReporter.reportDriverProblem(entry.getName(), e);
return;
}
try {
defineClass(baos.toByteArray(), 0, baos.size());
} catch (LinkageError e) {
problemReporter.reportDriverProblem(entry.getName(), e);
}
}
}
}
Jar 加载成功,我可以获得驱动程序的实例。
景点
在连接到数据库的调用中我收到此错误:
java.lang.NoClassDefFoundError: org/postgresql/hostchooser/HostRequirement
at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:107)
at org.postgresql.core.ConnectionFactory.openConnection(ConnectionFactory.java:66)
at org.postgresql.jdbc.PgConnection.<init>(PgConnection.java:215)
at org.postgresql.Driver.makeConnection(Driver.java:406)
at org.postgresql.Driver.connect(Driver.java:274)
在堆栈跟踪中,我看到 org.postgresql.Driver
的工作实例正在寻找名为 org/postgresql/hostchooser/HostRequirement
的 class。
假设
我的 JarClassloader
不加载匿名嵌套 classes.
问题
我应该怎么做才能成功加载 jar 中的所有 classes?
您需要按照 classloader 需要它们的顺序加载 classes,而不是按照它们恰好在 JAR 文件中的顺序。因此,您需要重写 findClass()
方法并在此时搜索 JAR 文件以查找所请求的 class。
使用文件会简单很多