У меня есть проект 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);
}
Перехватывается исключение нулевого указателя, что означаетчто ресурс не может быть найден.Я предполагаю, что это потому, что агент предполагает, что он ищет в своем собственном целевом каталоге и не рассматривает (или не может получить к нему доступ) целевой каталог для среды выполнения.
Я использую Maven, поэтому есть src и целькаталог для агента, а также src и целевой каталог для среды выполнения.Моя цель состоит в том, чтобы класс Agent в модуле агента вызывал метод main()
класса LangagentApplication, расположенного в .jar в целевом каталоге среды выполнения, для чего требуется, чтобы Maven сначала смог построить среду выполнения, а затем разрешить агентудобавьте среду выполнения к пути к классам.
У меня следующие вопросы: Как мне настроить файлы maven pom.xml, чтобы Agent.java
мог найти .jar, будь то с помощью команд сборки / localзависимости / etc, учитывая, что путь к классу при запуске не включает среду выполнения .jar?
Спасибо.