java - 如何访问位于源文件夹中的 Jar 文件?

标签 java jdbc classpath h2

在我的 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 构建路径对我来说是没有选择的。

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

预先感谢所有有用的想法!

亲切的问候,马蒂亚斯

最佳答案

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

一种方法是编写自己的 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 等等)。


No it's not a homework, but an online build system that uses my classes under my/app/* and several other classes (not from me) to automatically build the whole solution. Anyway, I can't give you more details on the internals of this system, as I don't know them. As said, I simply have to live with it, and that is why I am asking here...

听起来您正在 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 code> 然后您可以将其传递给 URLClassLoader。

如果没有其他办法,请上传库的源代码并将它们与您的项目一起编译。

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

关于java - 如何访问位于源文件夹中的 Jar 文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10541765/

相关文章:

Eclipse 中的 java.lang.ClassNotFoundException : com. mysql.jdbc.Driver 即使引用了 mysql-connector jar

sql-server - Pentaho水壶: cannot connect to MS SQL Server Express

java - 运行 Java 程序链接到第三方库 (java -jar) 问题(尝试了多种方法)

java - ThreadDeath 上的线程生命周期

java - 带 Spring Boot 的 Jackson : control object substitution for specific method

java - Spring Controller 中的圆形 View

java - Firebird CHAR_TO_UUID,因 GDS 异常而失败。 335544606

java - 类在类路径中时出现 ClassDefNotFoundError

android - Gradle 失败可能是因为这个 Flutter 应用程序中的 AndroidX 不兼容

java - JAXB 这会导致无限深的XML