简体   繁体   English

指定Java代理的类路径

[英]Specifying the classpath for a java agent

For context, I'm working on a tool called Randoop. 对于上下文,我正在开发一个名为Randoop的工具。 What I need to do is to be able to replace certain method calls at runtime using the Java agent. 我需要做的是能够使用Java代理在运行时替换某些方法调用。 Specifically, I want to replace calls to Random() with Random(0). 具体来说,我想将对Random()的调用替换为Random(0)。

I have the following directory structure: 我有以下目录结构:

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

I'm running all commands from the test_randoop directory. 我正在运行来自test_randoop目录的所有命令。

Random.java's contents are: Random.java的内容是:

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;
  }
}

I want to get the class Random at runtime with the following line where classname is defined as replace.java.util.Random 我想在运行时使用以下行获取类Random,其中以下行将classname定义为replace.java.util.Random

Class<?> methodClass = Class.forName(classname);

However, this code is being called from the replacecall.jar file which is the Java agent that I'm using to replace calls. 但是,此代码是从replacecall.jar文件中调用的,该文件是我用来替换调用的Java代理。 This seems to be a problem because the agent doesn't seem to be aware of the replace.java.util.Random class. 这似乎是一个问题,因为代理似乎不知道replace.java.util.Random类。

To elaborate, the Java program that I'm running is executed with the following command: 详细地说,我正在运行的Java程序是使用以下命令执行的:

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

The problem is that the replace.java.util.Random class is never found on the classpath and the forName method throws a ClassNotFoundException . 问题是, replace.java.util.Random类是从未在类路径上发现forName方法抛出一个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());
}

and the resulting output is: 结果输出为:

/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

What could I be missing here? 我在这里可能想念什么? Is there a different classpath that must be provided to the Java agent argument? 是否必须为Java代理参数提供不同的类路径? 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? 为什么系统类装入器将test_randoop目录作为类路径的一部分列出, test_randoop replace/java/util Random类?

Bootstrap classloader (which loads JDK classes) and system classloader (which loads application classes) are different things. Bootstrap类加载器(加载JDK类)和系统类加载器(加载应用程序类)是不同的东西。

By default, Java agent is loaded by the system classloader, and it has access to the classes specified in -classpath . 默认情况下,Java代理由系统类加载器加载,并且可以访问-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. 基本上,您需要删除-Xbootclasspath以便代理也可以看到用户类。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM