我有一个带有两个独立组件的Java项目,它们构建为两个独立的.jar文件,其中一个是代理,另一个是运行时。
我试图让代理(Agent.java
)在运行时运行main()
LangagentApplication.java
方法,首先使用ClassLoader.getResource()
来访问包含的.jar文件LangagentApplication,但我实际上无法访问运行时.jar文件。我目前正在使用以下内容:getResource("target/runtime.jar")
,它只是返回null
。打印类路径时,不包括运行时.jar。
请参阅下面的目录结构。
project
--pom.xml
--agent
--src
--main/java/.../Agent.java
--target
--agent.jar
--...
--pom.xml
--runtime
--src
--main/java/.../LangagentApplication.java
--target
--runtime.jar
--...
--pom.xml
注意:
- 为了简单起见,我将jar文件称为agent.jar
和runtime.jar
- 它们的实际名称更长更麻烦。
- 代理程序和运行时都使用相同的程序包(com.spnlangagent.langagent
)
- Java 1.8
我正在运行Maven和Java,如下所示(来自项目目录):
mvn package
java -cp /path/to/project/runtime/target/runtime.jar -javaagent:/path/to/project/agent/target/agent.jar -jar otherjar.jar
我目前正在执行以下代码:
private static void startRuntime(String agentArgs) throws Exception {
System.out.println("startRuntime: now running with agentArgs: " + agentArgs);
//Create a temporary file for the jar
File output = File.createTempFile("runtime", "jar");
//Attempt to load the runtime jar
try (InputStream inputStream = ClassLoader.getSystemClassLoader().getResource("target/runtime.jar").openStream()) {
Files.copy(inputStream, output.toPath(), StandardCopyOption.REPLACE_EXISTING);
} catch(NullPointerException npe) {
System.out.println("Null Pointer Exception when trying to get runtime agent jar. Since it was not found, aborting.");
npe.printStackTrace();
System.exit(1);
}
//NOTE: This is as far as the code ever gets - remainder of method kept to show intention
System.out.println("startRuntime: now creating runtime class loader");
//Handle classloaders.
ClassLoader extClassLoader = ClassLoader.getSystemClassLoader().getParent();
URL[] runtimejarurl = {output.toURI().toURL()};
ClassLoader runtimeClassLoader = new URLClassLoader(runtimejarurl, null);
System.out.println("startRuntime: now replacing class loader parent field");
//Replaces the native bootstrap class loader with ours
Field f = ClassLoader.class.getDeclaredField("parent");
f.setAccessible(true);
f.set(extClassLoader, runtimeClassLoader);
f.setAccessible(false);
System.out.println("startRuntime: now running Langagent Application main");
//Have the system class loader load our runtime agent class.
Class<?> runtimeClass = ClassLoader.getSystemClassLoader().loadClass("com.spnlangagent.langagent.LangagentApplication");
//Run the main method of the runtime agent
runtimeClass.getDeclaredMethod("main", String.class).invoke(null, agentArgs);
}
正在捕获Null指针异常,这意味着无法找到资源。我假设这是因为代理假定它在自己的目标目录中查找并且没有考虑(或不能访问)运行时的目标目录。
我正在使用Maven,因此代理有一个src和一个目标目录,运行时有一个src和一个目标目录。我的目标是让代理模块中的Agent类调用位于运行时目标目录中.jar中的LangagentApplication类的main()
方法,这要求Maven能够首先构建运行时然后允许代理将运行时添加到其类路径。
我的问题如下:
我应该如何配置我的maven pom.xml文件以允许Agent.java
找到.jar,无论是通过构建命令/本地依赖/等,假设运行时的类路径不包含运行时.jar?
谢谢。