Java 如何调整pom.xml以访问同一个包中但不同构建目录中的jar?
我有一个Java项目,它有两个独立的组件,构建成两个独立的.jar文件,其中一个是代理,另一个是运行时 我试图让代理(Java 如何调整pom.xml以访问同一个包中但不同构建目录中的jar?,java,maven,dependencies,classloader,pom.xml,Java,Maven,Dependencies,Classloader,Pom.xml,我有一个Java项目,它有两个独立的组件,构建成两个独立的.jar文件,其中一个是代理,另一个是运行时 我试图让代理(agent.java)在运行时运行LangagentApplication.java的main()方法,首先使用ClassLoader.getResource()访问包含LangagentApplication的.jar文件,但我在实际访问runtime.jar文件时遇到问题。我目前正在使用以下命令:getResource(“target/runtime.jar”),它只是返回n
agent.java
)在运行时运行LangagentApplication.java
的main()
方法,首先使用ClassLoader.getResource()
访问包含LangagentApplication的.jar文件,但我在实际访问runtime.jar文件时遇到问题。我目前正在使用以下命令:getResource(“target/runtime.jar”)
,它只是返回null
。打印类路径时,不包括runtime.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,如下所示(从项目目录): 我目前正在执行以下代码:
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);
}
private static void startRuntime(字符串agentArgs)引发异常{
System.out.println(“startRuntime:现在与agentArgs一起运行:“+agentArgs”);
//为jar创建一个临时文件
文件输出=File.createTempFile(“运行时”、“jar”);
//尝试加载运行时jar
try(InputStream InputStream=ClassLoader.getSystemClassLoader().getResource(“target/runtime.jar”).openStream()){
copy(inputStream,output.toPath(),StandardCopyOption.REPLACE_EXISTING);
}捕获(NullPointerException npe){
System.out.println(“尝试获取运行时代理jar时出现空指针异常,因为找不到,正在中止”);
npe.printStackTrace();
系统出口(1);
}
//注意:这是代码所能得到的——保留方法的剩余部分以显示意图
System.out.println(“startRuntime:now creating runtime class loader”);
//处理类装入器。
ClassLoader extClassLoader=ClassLoader.getSystemClassLoader().getParent();
URL[]runtimejarurl={output.toURI().toURL()};
ClassLoader runtimeClassLoader=新的URLClassLoader(runtimejarurl,null);
System.out.println(“startRuntime:现在替换类加载器父字段”);
//将本机引导类装入器替换为我们的
字段f=ClassLoader.class.getDeclaredField(“父项”);
f、 setAccessible(true);
f、 set(extClassLoader、runtimeClassLoader);
f、 setAccessible(false);
System.out.println(“startRuntime:now running Langagent Application main”);
//让系统类加载器加载我们的运行时代理类。
类runtimeClass=ClassLoader.getSystemClassLoader().loadClass(“com.spnlangagent.langagent.LangagentApplication”);
//运行运行时代理的main方法
runtimeClass.getDeclaredMethod(“main”,String.class).invoke(null,agentArgs);
}
正在捕获空指针异常,这意味着找不到资源。我假定这是因为代理假定它正在查看自己的目标目录,并且没有考虑(或无法访问)运行时的目标目录
我使用的是Maven,所以代理有一个src和一个目标目录,运行时有一个src和一个目标目录。我的目标是让代理模块中的代理类调用位于运行时目标目录.jar中的LangagentApplication类的main()
方法,这要求Maven能够首先构建运行时,然后允许代理将运行时添加到其类路径中
我的问题如下:
考虑到运行时的类路径不包括runtime.jar,我应该如何配置maven pom.xml文件以允许Agent.java
定位.jar,无论是通过构建命令/本地依赖项/etc
谢谢。您无法将target/runtime.jar作为类资源。这个jar已经添加到类路径中,因此jar的内容是可用的,而不是jar本身。如果您希望将jar作为一个可读的(出于某种原因)资源,那么target/runtime.jar必须捆绑在agent.jar中。我想你不想那样。这两个jar在类路径中都可用吗?如果是,为什么不直接调用LangagentApplication而不进行反思呢。如果没有,则使用UrlClassloader而不进行任何复制。阐明您的意图。我想做的是从代理jar中的一个方法执行LangagentApplication的主方法(在运行时jar中)。您没有解释的是这两个jar是否在类路径中?在执行代理类时,您是如何放置这两个jar的。我正在按如下方式运行代理:
java-javaagent:/Users/andrewfan/Desktop/Spn LangAgent/agent/target/Spn-LangAgent-agent-0.0.jar-jar
我目前没有直接为代理或运行时设置-cp。jar文件相对于项目目录的位置与我的问题中描述的完全相同。@gagansingh我做了一些测试,没有,运行时jar根本不在类路径中-只有运行代理的代理和目标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);
}