Java 클래스가로드 된 위치 찾기


184

누구나 Java 클래스 로더가 실제로 클래스를로드하는 위치를 프로그래밍 방식으로 찾는 방법을 알고 있습니까?

나는 종종 클래스 패스가 길어지고 수동 검색이 실제로 옵션이 아닌 큰 프로젝트에서 일합니다. 최근 에 클래스 로더가 클래스 경로에 있었기 때문에 클래스 로더가 잘못된 버전의 클래스를로드하는 데 문제 가있었습니다 .

그렇다면 실제 클래스 파일의 디스크 위치를 클래스 로더에게 알려주려면 어떻게해야합니까?

편집 : 버전 불일치 (또는 다른 것)로 인해 클래스 로더가 실제로 클래스를로드하지 못하면 어쨌든 읽기 전에 어떤 파일을 읽으려고합니까?


4
@JarrodRoberson 나는 이것이 2008 년에이 질문이 제기되었고 그 질문이 2012 년에 요청 되었기 때문에 이것이 stackoverflow.com/questions/11747833/ 의 사본으로 간주되어서는 안된다고 생각하지 않습니다
luke

답변:


189

예를 들면 다음과 같습니다.

package foo;

public class Test
{
    public static void main(String[] args)
    {
        ClassLoader loader = Test.class.getClassLoader();
        System.out.println(loader.getResource("foo/Test.class"));
    }
}

이것은 인쇄되었습니다 :

file:/C:/Users/Jon/Test/foo/Test.class

32
중복 입력을 줄이려면 더 짧은 버전을 사용할 수도 있습니다 Test.class.getResource("Test.class"). 패키지 이름을 반복하지 않습니다.
meriton

1
.groovy 파일에서 클래스를 컴파일하면 어떻게 되나요?
Ondra Žižka

35
@meriton : 또는 refactorinsgs에서 살아남 으려면 :Test.class.getResource(Test.class.getSimpleName() + ".class")
leonbloy

1
의 경우 BouncyCastleProvider전체 패키지 이름 그러나 필요합니다.
Pavel Vlasov

3
그것은 가능하다 getClassLoader()으로 돌아 가기 null. 이를 처리하기위한이 방법의 확장에 대해서는 여기 를 참조 하십시오 .
OldCurmudgeon

100

소스를 조작하지 않고 클래스가로드되는 위치를 찾는 또 다른 방법은 다음 옵션을 사용하여 Java VM을 시작하는 것입니다. -verbose:class


6
이것은 매우 잘 작동하며 null ClassLoader를 사용하여 클래스를 처리하는 데 문제가 없습니다
lexicalscope

2
@ries 프로그래밍 방식 으로이 작업을 수행 할 필요가 없다면 분명히 갈 길이며 내 문제를 해결했습니다. 그러나 OP는 프로그래밍 방식 으로이 작업을 수행하는 방법을 구체적으로 요구했습니다.
SantiBailors

80
getClass().getProtectionDomain().getCodeSource().getLocation();

4
그렇습니다. 보안 관리자가 설치되어 있고 필요한 권한이 없으면 작동하지 않습니다.
Tom Hawtin-tackline

1
참고로 NPE = 널 포인터 예외입니다. HTH!
Evgeni Sergeev

이 방법은 인스턴스에 대한 참조가있는 한 선호됩니다. 두 개의 다른 위치에서 동일한 클래스를로드 할 수 있기 때문입니다.
미구엘 핑

1
Java 9+ 모듈에서 호출 할 때도 작동하지 않습니다 (물론 2008 년에는 알 수 없었습니다).
Jeff G

28

이것이 우리가 사용하는 것입니다.

public static String getClassResource(Class<?> klass) {
  return klass.getClassLoader().getResource(
     klass.getName().replace('.', '/') + ".class").toString();
}

이것은 ClassLoader 구현에 따라 작동합니다. getClass().getProtectionDomain().getCodeSource().getLocation()


17

객체가 다음과 같은 경우 Jon의 버전이 실패합니다. ClassLoadernullBoot에 의해로드 된 것으로 보이는 것처럼 가 등록ClassLoader .

이 방법은 해당 문제를 처리합니다.

public static String whereFrom(Object o) {
  if ( o == null ) {
    return null;
  }
  Class<?> c = o.getClass();
  ClassLoader loader = c.getClassLoader();
  if ( loader == null ) {
    // Try the bootstrap classloader - obtained from the ultimate parent of the System Class Loader.
    loader = ClassLoader.getSystemClassLoader();
    while ( loader != null && loader.getParent() != null ) {
      loader = loader.getParent();
    }
  }
  if (loader != null) {
    String name = c.getCanonicalName();
    URL resource = loader.getResource(name.replace(".", "/") + ".class");
    if ( resource != null ) {
      return resource.toString();
    }
  }
  return "Unknown";
}

5

첫 번째 줄만 편집 : Main.class

Class<?> c = Main.class;
String path = c.getResource(c.getSimpleName() + ".class").getPath().replace(c.getSimpleName() + ".class", "");

System.out.println(path);

산출:

/C:/Users/Test/bin/

어쩌면 나쁜 스타일이지만 잘 작동합니다!


3

일반적으로 하드 코딩을 사용하지 않습니다. 먼저 className을 가져온 다음 ClassLoader를 사용하여 클래스 URL을 가져올 수 있습니다.

        String className = MyClass.class.getName().replace(".", "/")+".class";
        URL classUrl  = MyClass.class.getClassLoader().getResource(className);
        String fullPath = classUrl==null ? null : classUrl.getPath();

URL classUrl = MyClass.class.getClassLoader (). getResource ( "/"+ className);
앤드류 코츠

MyClass.class는 중요한 부분입니다. getClass ()는 프록시를 반환 할 수 있습니다! 그런 다음 MyClass $$ EnhancerBySpringCGLIB $$ a98db882.class 및 null URL과 같은 이름을 얻을 수 있습니다.
jalmasi


1

간단한 방법 :

System.out.println (java.lang.String.class.getResource (String.class.getSimpleName () + ". class"));

예 :

jar : 파일 : / D : /Java/jdk1.8/jre/lib/rt.jar! /java/lang/String.class

또는

문자열 obj = "간단한 테스트"; System.out.println (obj.getClass (). getResource (obj.getClass (). getSimpleName () + ". class"));

예 :

jar : 파일 : / D : /Java/jdk1.8/jre/lib/rt.jar! /java/lang/String.class


0

이 접근 방식은 파일과 jar 모두에서 작동합니다.

Class clazz = Class.forName(nameOfClassYouWant);

URL resourceUrl = clazz.getResource("/" + clazz.getCanonicalName().replace(".", "/") + ".class");
InputStream classStream = resourceUrl.openStream(); // load the bytecode, if you wish

-1

이라는 클래스를 사용한다고 가정하면 MyClass다음이 작동합니다.

MyClass.class.getClassLoader();

.class 파일의 디스크 위치를 가져올 수 있는지 여부는 클래스 로더 자체에 따라 다릅니다. 예를 들어 BCEL과 같은 것을 사용하는 경우 특정 클래스에는 온 디스크 표현이 없을 수도 있습니다.


클래스 로딩에 사용 된 ClassLoader를 반환합니다. .class 파일이 어디에 있지 않습니까?
Koray Tugay

1
아닙니다. 클래스 로더는 실제로 완전히 다른 클래스 경로를 참조 할 수 있습니다. 즉, 실제 클래스 위치를 완전히 파악할 수는 없습니다.
Tomáš Zato-복원 모니카
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.