在我的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中看起来像这样:
<project>/src/my/app/MyApp.java // main class of my application
<project>/src/my/app/sub/package/h2.jar // how to access this?
<project>/libs/h2.jar // loading from here works
我知道这很愚蠢,但不幸的是我必须使用这个奇怪的设置。但我不知道:如何编辑我的Java代码(如上所列)以便使用此设置?
编辑:这也必须在Eclipse之外工作,所以将JAR文件添加到Eclipse中的Java Build Path对我来说是没有选择的。
EDIT2:我已经尝试加载“jar:file:my / app / sub / package / h2.jar!/”,但这对我没用。
提前感谢所有有用的想法!
亲切的问候,马蒂亚斯
答案 0 :(得分:2)
在某些框架中,可以使用classpath:
前缀来引用JAR中的文件。 我怀疑URLClassLoader本身支持它,但是值得一试(例如但是因为这不适用于URLClassLoader,所以还有其他方法:classpath:/my/app/sub/package/h2.jar
)。
这样做的一种方法是编写自己的ClassLoader,它从类路径中读取JAR文件(使用getResourceAsStream),将其解压缩(使用ZipInputStream)到内存(例如字节数组的映射)并从那里加载类。
另一种更简单的方法是从类路径中读取JAR文件并将其写入临时文件。然后你可以使用普通的URLClassLoader从中加载类。这样做的缺点是必须将文件写入文件,并且在JVM退出(unless using Java 7或更高版本)之前,可能无法删除该文件。
我正在使用第二种方法(复制到临时文件)in one project,尽管我正在使用launch an external process。我很想知道为什么你有这样的要求。如果只是将整个应用程序放在一个JAR中,有许多更简单的方法可以实现(Maven Assembly Plugin,Maven Shade Plugin,Jar Jar Links,One-JAR等等)。
不,这不是一个家庭作业,而是一个在我的/ app / *和其他几个类(不是来自我)下使用我的类来自动构建整个解决方案的在线构建系统。无论如何,我不能给你更多关于这个系统内部的细节,因为我不知道它们。如上所述,我只需忍受它,这就是我在这里问的原因......
听起来你在WTF环境中工作(它有名字吗?),所以这里有一些方法可以开始攻击它:
了解有关您的环境的更多信息,尤其是以下的绝对文件路径:保存源文件的目录,保存生成的.class文件的目录以及运行程序时的当前工作目录。
如果您可以获得程序在运行时打印的任何类型的输出,您可以在应用程序中添加一些调试代码,您可以使用File.listFiles()来抓取计算机的目录树。如果只能从编译时发生的事情中获得输出,那么可以在编译期间通过创建自己的annotation processor(自Java 6以来apt是javac的一部分)来执行自己的代码,尽管我不确定是否必须先单独编译注释处理器。
可以从user.dir
系统属性读取工作目录,并且可以从java.class.path
系统属性获取类文件的位置(除非使用自定义类加载器)。无法保证源目录中的JAR文件会被复制到类路径中,因此您可能需要进行一些查看。
然后,当您知道JAR文件的文件路径时,您可以使用new File("path/to/h2.jar").toURI().toURL()
获取一个URL,然后您可以将其传递给URLClassLoader。
如果没有其他工作,请上传库的源代码并与项目一起编译。
从长远来看,尝试将WTF构建环境替换为使用标准构建工具(例如Maven)和公共CI服务器(例如Jenkins)的构建环境。项目有很多库依赖项是正常的,所以你不需要破解构建环境来使用它们。