如何访问位于源文件夹中的 Jar 文件?
Posted
技术标签:
【中文标题】如何访问位于源文件夹中的 Jar 文件?【英文标题】:How to access Jar file located within source folders? 【发布时间】:2012-05-10 20:37:15 【问题描述】:在我的 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!/”,但这对我不起作用。
提前感谢所有有用的想法!
亲切的问候,马蒂亚斯
【问题讨论】:
你试过 jar:file:my/app/sub/package/h2.jar 了吗? 您描述的“奇怪的设置”是一个非常正常的目录结构。没有理由将 JAR 文件放在您的src
文件夹中。听起来您的类路径中根本没有 h2.jar
。
@thinksteep:是的,试过了,但没用。
@matt b:我知道没有理由将 JAR 文件放入 src 文件夹中——但正如我所说,我必须忍受它,我无法改变这个要求。
现在这是一个奇怪的构建系统 - 不必要地使开发人员的生活复杂化。你是说这是商业作品?将您的故事提交给thedailywtf.com 怎么样?)
【参考方案1】:
在某些框架中,引用 JAR 中的文件可以使用 classpath:
前缀来完成。 我怀疑 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 等等)。
不,这不是作业,而是一个在线构建系统,它使用我在 my/app/* 下的类和其他几个类(不是我的)来自动构建整个解决方案。无论如何,我无法向您提供有关该系统内部结构的更多详细信息,因为我不了解它们。如前所述,我只需要忍受它,这就是我在这里问的原因......
听起来你是在 WTF 环境中工作(它有名字吗?),所以这里有一些方法可以开始破解它:
详细了解您的环境,尤其是以下绝对文件路径:保存源文件的目录、保存生成的 .class 文件的目录以及程序运行时的当前工作目录。
如果您可以获得程序在运行时打印的任何类型的输出,您可以将一些调试代码放入您的应用程序中,您可以在其中使用File.listFiles() 来抓取机器的目录树。如果您只能从编译时发生的事情中获得输出,则可以通过创建自己的annotation processor(apt 是 javac 自 Java 6 以来的一部分)在编译期间执行您自己的代码,尽管我不确定注释是否处理器必须先单独编译。
可以从user.dir
系统属性读取工作目录,并且可以从java.class.path
系统属性获取类文件的位置(除非使用自定义类加载器)。无法保证源目录中的 JAR 文件会被复制到类路径中,因此您可能需要四处查看。
然后,当您知道 JAR 文件的文件路径后,您可以使用 new File("path/to/h2.jar").toURI().toURL()
获取指向它的 URL,然后您可以将其传递给 URLClassLoader。
如果没有其他方法,请上传库的源代码并将它们与您的项目一起编译。
从长远来看,尝试将 WTF 构建环境替换为使用标准构建工具(如 Maven)和通用 CI 服务器(如 Jenkins)的构建环境。项目有很多库依赖项是正常的,因此您不需要绕过构建环境来使用它们。
【讨论】:
不幸的是,使用“类路径:”不起作用。我必须使用这个环境,因为它是一种自动的在线构建系统,我只能在 my/app/* 下上传文件和文件夹 我已经更新了我的答案。您可以使用这些提示了解更多关于环境的信息吗?环境是否公开,以便我们查看? 我猜你是对的,这真的是一个 WTF 环境。我将尝试与它的所有者取得联系,并找出所有类文件最终所在的目录。另外,也许他可以手动将 .jar 文件复制到适当的目录中...以上是关于如何访问位于源文件夹中的 Jar 文件?的主要内容,如果未能解决你的问题,请参考以下文章
Tomcat下webapps夹中root文件夹作用及如何发布项目至root文件夹中
在与位于项目目录中的 .jar 文件相同的文件夹中创建一个文件