2017-12-22 4 views
0

컨텍스트에서 Randoop이라는 도구를 사용하고 있습니다. Java Agent를 사용하여 런타임에 특정 메소드 호출을 대체 할 수 있어야합니다. 특히 Random()에 대한 호출을 Random (0)으로 대체하려고합니다.Java 에이전트의 클래스 경로 지정

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

내가 classnamereplace.java.util.Random

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

으로 정의 된 다음 줄에 런타임에 Random 클래스를 얻으려면이 코드가 호출되고 replacecall.jar 파일에서 호출을 대체하는 Java 에이전트입니다. 이것은 에이전트가 replace.java.util.Random 클래스를 인식하지 못하는 것 때문에 문제가되는 것 같습니다.

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을 발생한다는 것입니다 :

, 나는 다음과 같은 명령을 실행하고 있는데, Java 프로그램을 자세히 설명합니다.

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 디렉토리를 클래스 경로의 일부로 나열하는 이유는 무엇입니까? Randomreplace/java/util 디렉토리는 찾을 수 없습니까?

답변

1

(JDK 클래스를로드하는) 부트 스트랩 클래스 로더와 (애플리케이션 클래스를로드하는) 시스템 클래스 로더는 다른 것들입니다.

기본적으로 Java 에이전트는 시스템 클래스 로더에 의해로드되고 -classpath에 지정된 클래스에 액세스 할 수 있습니다. 그러나 귀하의 경우 에이전트가 -Xbootclasspath 옵션으로 인해 부트 스트랩 클래스 로더에 의해로드되고 시스템 클래스 로더의 클래스가 표시되지 않습니다.

상담원이 사용자 등급을 볼 수 있도록 기본적으로 -Xbootclasspath을 제거해야합니다.

+0

제안 해 주셔서 감사합니다. 에이전트가 JDK 클래스를 볼 수 있도록'-Xbootclasspath' 옵션이 필요한 경우 어떻게합니까? 따라서'-Xbootclasspath' 인자를 유지하면 Java 에이전트가 시스템 클래스 로더의 클래스를 볼 수있게 할 수 있습니까? – wayway

+1

@wayway 에이전트는'-Xbootclasspath'가 없어도 JDK 클래스를 봅니다. 클래스 로더는 계층 구조를 구성합니다. 부트 스트랩 -> 시스템 -> 응용 프로그램 클래스 로더. 자식 클래스 로더에 의해로드 된 클래스는 모든 클래스의 부모 클래스 로더에 액세스 할 수 있습니다. – apangin

관련 문제