指定Java代理的类路径 [英] Specifying the classpath for a java agent

查看:104
本文介绍了指定Java代理的类路径的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对于上下文,我正在开发一个名为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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆