指定java代理的类路径

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了指定java代理的类路径相关的知识,希望对你有一定的参考价值。

对于上下文,我正在开发一个名为Randoop的工具。我需要做的是能够使用Java代理在运行时替换某些方法调用。具体来说,我想用Random(0)替换对Random()的调用。

我有以下目录结构:

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目录中的所有命令。

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

我想在运行时使用以下行获取Random类,其中classname定义为replace.java.util.Random

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

但是,从replacecall.jar文件调用此代码,该文件是我用来替换调用的Java代理。这似乎是一个问题,因为代理似乎并不知道replace.java.util.Random类。

详细说明,我正在运行的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

问题是在类路径上找不到replace.java.util.Random类,forName方法抛出ClassNotFoundException

我试图在运行时使用以下代码段打印出系统类路径:

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目录列为类路径的一部分,但是找不到Random中的类replace/java/util

答案

Bootstrap类加载器(加载JDK类)和系统类加载器(加载应用程序类)是不同的东西。

默认情况下,Java代理程序由系统类加载器加载,并且可以访问-classpath中指定的类。但是在你的情况下,由于-Xbootclasspath选项,代理程序由引导程序类加载器加载,并且它不会从系统类加载器中看到类。

您基本上需要删除-Xbootclasspath,以便代理也可以看到用户类。

以上是关于指定java代理的类路径的主要内容,如果未能解决你的问题,请参考以下文章

java 如何使用反射 加载指定路径下的类文件(.class)

java动态代理(JDK和cglib)

Java扫描classpath指定包路径下所有class

动态代理

没有默认构造函数可用于指定的类,结构或联合[重复]

Eclipse Java 构建路径