指定Java代理的类路径 [英] Specifying the classpath for a java agent
问题描述
对于上下文,我正在开发一个名为Randoop的工具.我需要做的是能够在运行时使用Java代理替换某些方法调用.具体来说,我想将对Random()的调用替换为Random(0).
For context, I'm working on a tool called Randoop. What I need to do is to be able to replace certain method calls at runtime using the Java agent. Specifically, I want to replace calls to Random() with Random(0).
我具有以下目录结构:
test_randoop/
randoop.jar
replacecall.jar
replacement_file.txt
ClassWithRandom.java
ClassWithRandom.class
replace/
java/
util/
Random.java
Random.class // created with "javac Random.java" command
我正在运行test_randoop
目录中的所有命令.
I'm running all commands from the test_randoop
directory.
Random.java的内容是:
Random.java's contents are:
package replace.java.util;
public class Random {
/** Default mock for {@code Random()}. Replaces call with {@code Random(0)}. */
public static java.util.Random randomWithSeedZero() {
return new java.util.Random(0);
}
public static int returnZero() {
return 0;
}
}
我想在运行时使用以下行获取类Random,其中将classname
定义为replace.java.util.Random
I want to get the class Random at runtime with the following line where classname
is defined as replace.java.util.Random
Class<?> methodClass = Class.forName(classname);
但是,此代码是从replacecall.jar文件中调用的,replacecall.jar文件是我用来替换调用的Java代理.这似乎是一个问题,因为代理似乎不知道replace.java.util.Random
类.
However, this code is being called from the replacecall.jar file which is the Java agent that I'm using to replace calls. This seems to be a problem because the agent doesn't seem to be aware of the replace.java.util.Random
class.
详细来说,我正在运行的Java程序是使用以下命令执行的:
To elaborate, the Java program that I'm running is executed with the following command:
java -ea -classpath .:randoop.jar -Xbootclasspath/a:/home/waylonh/test_randoop/replacecall.jar -javaagent:/home/waylonh/test_randoop/replacecall.jar="--replacement-file=replacement_file.txt --debug=true --verbose=true" randoop.main.Main gentests --testclass=ClassWithRandom --output-limit=10
问题在于replace.java.util.Random
类在类路径中从未找到,并且forName
方法抛出ClassNotFoundException
.
The problem is that the replace.java.util.Random
class is never found on the classpath and the forName
method throws a ClassNotFoundException
.
我试图在运行时使用以下代码段打印出系统类路径:
I've attempted to print out the system classpath at runtime with the following snippet:
ClassLoader classLoader = ClassLoader.getSystemClassLoader();
for (URL u : ((URLClassLoader) classLoader).getURLs()) {
System.out.println(u.getFile());
}
的结果是:
/home/waylonh/test_randoop/
/home/waylonh/randoop/build/libs/randoop-all-3.1.5.jar
/home/waylonh/randoop/build/libs/replacecall-3.1.5.jar
我在这里可能想念什么?是否必须为Java代理参数提供不同的类路径?为什么系统类加载器将test_randoop
目录作为类路径的一部分列出,却又找不到replace/java/util
中的类Random
?
What could I be missing here? Is there a different classpath that must be provided to the Java agent argument? Why is it that the system class loader lists the test_randoop
directory as part of the classpath, and yet the class Random
within replace/java/util
cannot be found?
推荐答案
Bootstrap类加载器(加载JDK类)和系统类加载器(加载应用程序类)是不同的.
Bootstrap classloader (which loads JDK classes) and system classloader (which loads application classes) are different things.
默认情况下,Java代理由系统类加载器加载,并且可以访问-classpath
中指定的类.但是,在您的情况下,由于-Xbootclasspath
选项,该代理由引导类加载器加载,并且看不到系统类加载器中的类.
By default, Java agent is loaded by the system classloader, and it has access to the classes specified in -classpath
. But in your case the agent is loaded by the bootstrap classloader because of -Xbootclasspath
option, and it does not see the classes from the system classloader.
您基本上需要删除-Xbootclasspath
,以便代理也可以看到用户类.
You basically need to remove -Xbootclasspath
so that the agent could see user classes, too.
这篇关于指定Java代理的类路径的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!