시스템 ClassLoader가 런타임에 지정된 .class 파일을 로드하도록 하는 것이 가능합니까?

StackOverflow https://stackoverflow.com/questions/1873916

문제

과제에 대한 정적 분석 도구를 작성 중인데 ASM 라이브러리를 사용하여 Java 바이트코드를 분석합니다.우리가 사용하는 ASM 부분 중 하나는 클래스가 ClassLoader에서 로드되도록 요구합니다(또는 적어도 요구하는 것처럼 보입니다).

우리는 이 도구가 클래스 경로에 파일을 요구하지 않고도 .class 파일을 분석할 수 있기를 바랐습니다.우리는 이미 런타임에 지정된 디렉터리에서 .classes를 로드하고 InputStream을 사용하여 읽습니다.이는 대부분의 경우 ASM에 허용됩니다.등의 수업이 있습니다. SimpleVerifier, 클래스를 로드하려고 시도합니다.

이 시나리오에서 로드할 .class 파일을 등록하여 다음을 호출하는 것이 가능합니까? Class.forName() 로드할래?아니면 이를 허용하도록 ClassLoader를 확장하는 쉬운 방법이 있습니까?


편집하다:에 대한 정보 URLClassLoader 유용했습니다.불행히도, Thread.currentThread().setContextClassLoader() 이 시나리오에서는 그 인스턴스가 작동하지 않았습니다.내가 호출하는 라이브러리 코드는 다음을 사용하여 인스턴스 초기화 시 검색하는 로더를 사용합니다. getClass().getClassLoader().

URLClassLoader를 설정할 때쯤에는 클래스가 초기화되지 않았으므로 contextClassLoader가 해당 클래스를 로드하지 않는 것 같습니다.

내가 응답을 올바르게 이해했는가?제3자 클래스를 로드하기 위해 URLClassLoader를 사용할 수 있습니까?

도움이 되었습니까?

해결책

거의.

어딘가에 수업을 컴파일 한 경우 UrlClassloader. 그런 다음이 클래스 로더를 현재 스레드의 클래스 로더로 설정할 수 있습니다. Thread.SetContextClassLoader (클래스 로더)

사용자는 현재 스레드 컨텍스트 클래스 로더를 얻고 클래스 정의에 액세스하는 데 사용할 수 있습니다.

다른 팁

우선, ASM은 클래스에 대한 정보를 얻기 위해 클래스 로더를 사용하지 않는 방식으로 사용할 수 있습니다.

ASM 프레임 워크에는 기본적으로 클래스를로드하는 여러 장소가 있지만 모든 장소는 자신의 하위 클래스에서 무시할 수 있습니다. 내 머리 꼭대기에서 :

  • classwriter.getCommonSuperClass () 메소드는 classwriter.compute_frames 플래그를 사용하는 경우에만 호출되며 클래스에 대한 정보를 얻기 위해 클래스 로더를 사용하지 않도록 덮어 쓸 수 있습니다. 그 예를 찾을 수 있습니다 ClasswriterComputeFramestest 그것은 classinfo 추상화를 소개합니다
  • 유사하게 SimpleVerifier.getClass () 메소드가 사용합니다 simpleverifier.isassignablefrom () 또한 후자를 덮어 쓰고 ClassInfo 추상화를 사용하여 공통 수퍼 유형을 찾을 수 있습니다. 내가 실수하지 않으면 Sagewerkz Project는 유형 패턴 일치 코드에서 비슷한 것을 구현했습니다. 또한 있습니다 simpleverifier.setclassloader () 자신의 클래스를로드하려는 경우 사용할 수있는 방법.

참고로, 태양의 JVMS에서로드 된 클래스는 Permgen 영역에 도달하여 언로드 할 수 없으므로, 피할 수있는 경우, 특히 공구가 도구가 될 경우에만 정적 코드 분석 목적으로 만 클래스를로드하는 것이 좋지 않습니다. IDE와 같은 오랜 프로세스에 통합됩니다.

내가 아는 한, 런타임에 시스템 클래스 로더를 확장 할 수는 없지만, 임의 위치 (JAR 또는 디렉토리)에서 클래스를 동적으로로드 할 수 있습니다. UrlClassloader.

애플리케이션을 시작할 때 "런처"를 설정해 볼 수 있습니다. URLClassLoader 클래스 경로와 자신의 위치를 ​​전달합니다. .class 해당 클래스로더에서 애플리케이션을 시작합니다.

SimpleVerifier 에 의해 로드됩니다. URLClassLoader 또한 추가 위치에서 클래스를 로드할 수도 있습니다.

예, 사용할 수 있습니다 UrlClassloader

런타임에 클래스를로드하는 테스트가 있습니다. 이 클래스는 클래스 경로에 있지 않으며 (그 문제에 대해 테스트가 실행될 때도 존재하지도 않습니다) 나중에로드되고 훌륭합니다.

코드는 다음과 같습니다.

void testHello() throws MalformedURLException, ClassNotFoundException {
    URL[] url = {
            new URL("file:/home/oreyes/testwork/")
    };

    try {
        new URLClassLoader(url).loadClass("Hello");
        throw new AssertionError("Should've thrown ClassNotFoundException");
    } catch ( ClassNotFoundException cnfe ){}


    c.process();// create the .class file 

    new URLClassLoader(url).loadClass("Hello");

    // it works!!
}

이것에서 가져 왔습니다 의문.

나는 내 자신의 클래스 로더를 아주 간단하게 만들었습니다.

 /**
 * Used to hold the bytecode for the class to be loaded.
 */
private final static ThreadLocal<byte[]> BYTE_CODE = new ThreadLocal<byte[]>();

@Override
protected Class<?> findClass(final String name) throws ClassNotFoundException {
    final byte[] bytes = BYTE_CODE.get();
    if (null == bytes) {
        throw new ClassNotFoundException(name);
    }
    return this.defineClass(null, bytes, 0, bytes.length);
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top