如何访问源文件夹中的Jar文件?

在我的Java项目中,我使用的是H2内存数据库,我必须在初始化应用程序时加载JDBC驱动程序。 我想/需要动态加载H2 .jar文件,所以我执行以下操作:

String classname = "org.h2.Driver"; URL u = new URL("jar:file:libs/h2.jar!/"); URLClassLoader ucl = new URLClassLoader(new URL[] { u }); Driver d = (Driver) Class.forName(classname, true, ucl).newInstance(); DriverManager.registerDriver(new DriverShim(d)); 

当我将H2 .jar文件放入我的Java源代码文件夹之外的“libs”文件夹中时(也就是说,在Eclipse中,这个“libs”目录与“src”文件夹处于同一级别),那么这种方法工作正常。 但是,不幸的是,我必须将这个H2 .jar文件放入源代码文件夹树中的文件夹中,但是在主类文件夹下面。

例如,我的Java包结构在Eclipse中如下所示:

 /src/my/app/MyApp.java // main class of my application /src/my/app/sub/package/h2.jar // how to access this? /libs/h2.jar // loading from here works 

我知道这是愚蠢的,但不幸的是我必须使用这个奇怪的设置。 但我不知道:我如何编辑我的Java代码(如上所列)才能使用此设置?

编辑:这也必须在Eclipse之外工作,所以将JAR文件添加到Eclipse中的Java Build Path对我来说是不可取的。

EDIT2:我已经尝试加载“jar:file:my / app / sub / package / h2.jar!/”,但这对我不起作用。

在此先感谢所有有用的想法!

亲切的问候,马蒂亚斯

在某些框架中,引用JAR中的文件可以使用classpath:前缀来完成。 我怀疑URLClassLoader本身是否支持它,但值得一试(例如classpath:/my/app/sub/package/h2.jar )。 但由于这不适用于URLClassLoader,以下是其他方法:

一种方法是编写自己的ClassLoader,它从类路径中读取JAR文件(使用getResourceAsStream),将其解压缩(使用ZipInputStream)到内存(例如字节数组的映射)并从那里加载类。

另一种稍微简单的方法是从类路径中读取JAR文件并将其写入临时文件。 然后,您可以使用普通URLClassLoader从中加载类。 这样做的缺点是必须将文件写入文件,并且在JVM退出之前可能无法删除该文件( 除非使用Java 7或更高版本)。

我在一个项目中使用第二种方法(复制到临时文件),虽然我正在使用它来启动外部进程 。 我很想知道为什么你有这样的要求。 如果只是将整个应用程序放在一个JAR中,那么有许多更简单的方法可以实现(Maven Assembly Plugin,Maven Shade Plugin,Jar Jar Links,One-JAR等等)。


不,这不是一个家庭作业,而是一个在我的/ app / *和其他几个类(不是来自我)下使用我的类来自动构建整个解决方案的在线构建系统。 无论如何,我不能给你更多关于这个系统内部的细节,因为我不知道它们。 如上所述,我只需忍受它,这就是我在这里问的原因……

听起来你在WTF环境中工作(它有一个名字吗?),所以这里有一些方法来开始黑客攻击它:

了解有关您的环境的更多信息,尤其是以下的绝对文件路径:保存源文件的目录,保存生成的.class文件的目录以及运行程序时的当前工作目录。

如果您可以获得程序在运行时打印的任何类型的输出,您可以在应用程序中放入一些调试代码,您可以使用File.listFiles()来抓取机器的目录树。 如果只能从编译时发生的事情中获得输出,那么可以在编译期间通过创建自己的注释处理器来执行自己的代码(自Java 6开始,apt是javac的一部分),尽管我不确定是否注释处理器必须先单独编译。

可以从user.dir系统属性读取工作目录,并且可以从java.class.path系统属性获取类文件的位置(除非使用自定义类加载器)。 无法保证源目录中的JAR文件将被复制到类路径中,因此您可能需要进行一些调查。

然后,当您知道JAR文件的文件路径时,您可以使用new File("path/to/h2.jar").toURI().toURL()获取它的URL,然后您可以将其传递给URLClassLoader。

如果没有其他工作,请上传库的源代码并与项目一起编译。

从长远来看,尝试使用标准构建工具(例如Maven)和公共CI服务器(例如Jenkins)替换WTF构建环境。 项目具有大量库依赖项是正常的,因此您不需要破解构建环境来使用它们。