使用 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。

使用文件会简单很多