클래스가 어느 JAR 파일인지 확인


154

나는 지금 API 사양을보고 IDE 앞에 있지 않습니다.

CodeSource src = MyClass.class.getProtectionDomain().getCodeSource();
if (src != null) {
    URL jar = src.getLocation();
}

클래스의 JAR 파일을 결정하고 싶습니다. 이것이 방법입니까?


2
콘솔에서 이것을 수행하는 방법이 있습니까? java -findjar -cp /some/path/with/libs/*.jar my.java.Class-> 같은 것 my.jar.
kub1x

답변:


191

예. 부트 스트랩 클래스 로더가로드 한 클래스를 제외한 모든 클래스에서 작동합니다. 결정하는 다른 방법은 다음과 같습니다.

Class klass = String.class;
URL location = klass.getResource('/' + klass.getName().replace('.', '/') + ".class");

notnoop이 지적한 것처럼 klass.getResource()메소드는 클래스 파일 자체의 위치를 ​​반환합니다. 예를 들면 다음과 같습니다.

jar:file:/jdk/jre/lib/rt.jar!/java/lang/String.class
file:/projects/classes/pkg/MyClass$1.class

getProtectionDomain().getCodeSource().getLocation()메소드는 jar 파일 또는 CLASSPATH의 위치를 ​​리턴합니다.

file:/Users/home/java/libs/ejb3-persistence-1.0.2.GA.jar
file:/projects/classes

이로 인해 클래스 이름에서 클래스 파일로의 맵핑이 가정됩니다. 익명 수업에 제대로 작동합니까? 중첩 된 수업?
Thorbjørn Ravn Andersen

1
이것은 jar 자체가 아닌 클래스의 URL을 가리 킵니다. jar 파일을 찾으려면 URL을 구문 분석해야합니다.
notnoop

@notnoop. 나는 대답을 명확히했다.
Chandra Patni

19
답변에 쓰여진 것과 정확히 반대의 방법입니다 getProtectionDomain().getCodeSource().getLocation(). jar 파일 위치를 얻으려면 사용 하십시오
peter

이 답변에 감사드립니다 . 이 질문에 답하게되었습니다 .
kriegaex

12

를 체크 아웃 LiveInjector.findPathJar()에서 롬복의 PatcherLiveInjector.java . 파일이 실제로 jar에 존재하지 않는 특별한 경우에 변경을 원할 수 있습니다.

/**
 * If the provided class has been loaded from a jar file that is on the local file system, will find the absolute path to that jar file.
 * 
 * @param context The jar file that contained the class file that represents this class will be found. Specify {@code null} to let {@code LiveInjector}
 *                find its own jar.
 * @throws IllegalStateException If the specified class was loaded from a directory or in some other way (such as via HTTP, from a database, or some
 *                               other custom classloading device).
 */
public static String findPathJar(Class<?> context) throws IllegalStateException {
    if (context == null) context = LiveInjector.class;
    String rawName = context.getName();
    String classFileName;
    /* rawName is something like package.name.ContainingClass$ClassName. We need to turn this into ContainingClass$ClassName.class. */ {
        int idx = rawName.lastIndexOf('.');
        classFileName = (idx == -1 ? rawName : rawName.substring(idx+1)) + ".class";
    }

    String uri = context.getResource(classFileName).toString();
    if (uri.startsWith("file:")) throw new IllegalStateException("This class has been loaded from a directory and not from a jar file.");
    if (!uri.startsWith("jar:file:")) {
        int idx = uri.indexOf(':');
        String protocol = idx == -1 ? "(unknown)" : uri.substring(0, idx);
        throw new IllegalStateException("This class has been loaded remotely via the " + protocol +
                " protocol. Only loading from a jar on the local file system is supported.");
    }

    int idx = uri.indexOf('!');
    //As far as I know, the if statement below can't ever trigger, so it's more of a sanity check thing.
    if (idx == -1) throw new IllegalStateException("You appear to have loaded this class from a local jar file, but I can't make sense of the URL!");

    try {
        String fileName = URLDecoder.decode(uri.substring("jar:file:".length(), idx), Charset.defaultCharset().name());
        return new File(fileName).getAbsolutePath();
    } catch (UnsupportedEncodingException e) {
        throw new InternalError("default charset doesn't exist. Your VM is borked.");
    }
}

2
매우 간단한 것을 얻기에는 지나치게 복잡해 보입니다. 방금 앉아서 이전에 찾은 것을 시도했지만 작동하는 것처럼 보입니다. 확인이 필요했습니다.

잘. 코드는 부트 클래스 경로의 파일을 처리하지 않으며 Chandra의 솔루션은 jar 파일이 아닌 파일에 URL을 반환하므로 jar 파일을 찾으려면 경로를 구문 분석해야합니다.
notnoop

2

사용하다

String path = <Any of your class within the jar>.class.getProtectionDomain().getCodeSource().getLocation().getPath(); 

여러 항목이 포함 된 경우 일부 하위 문자열 작업을 수행하십시오.


1
private String resourceLookup(String lookupResourceName) {



    try {

        if (lookupResourceName == null || lookupResourceName.length()==0) {
            return "";
        }
        // "/java/lang/String.class"

        // Check if entered data was in java class name format
        if (lookupResourceName.indexOf("/")==-1) {
            lookupResourceName = lookupResourceName.replaceAll("[.]", "/");
            lookupResourceName =  "/" + lookupResourceName + ".class";
        }

        URL url = this.getClass().getResource(lookupResourceName);
        if (url == null) {
            return("Unable to locate resource "+ lookupResourceName);

        }

        String resourceUrl = url.toExternalForm();

        Pattern pattern =
            Pattern.compile("(zip:|jar:file:/)(.*)!/(.*)", Pattern.CASE_INSENSITIVE);

        String jarFilename = null;
        String resourceFilename = null;
        Matcher m = pattern.matcher(resourceUrl);
        if (m.find()) {
            jarFilename = m.group(2);
            resourceFilename = m.group(3);
        } else {
            return "Unable to parse URL: "+ resourceUrl;

        }

        if (!jarFilename.startsWith("C:") ){
          jarFilename = "/"+jarFilename;  // make absolute path on Linux
        }

        File file = new File(jarFilename);
        Long jarSize=null;
        Date jarDate=null;
        Long resourceSize=null;
        Date resourceDate=null;
        if (file.exists() && file.isFile()) {

            jarSize = file.length();
            jarDate = new Date(file.lastModified());

            try {
                JarFile jarFile = new JarFile(file, false);
                ZipEntry entry = jarFile.getEntry(resourceFilename);
                resourceSize = entry.getSize();
                resourceDate = new Date(entry.getTime());
            } catch (Throwable e) {
                return ("Unable to open JAR" + jarFilename + "   "+resourceUrl +"\n"+e.getMessage());

            }

           return "\nresource: "+resourceFilename+"\njar: "+jarFilename + "  \nJarSize: " +jarSize+"  \nJarDate: " +jarDate.toString()+"  \nresourceSize: " +resourceSize+"  \nresourceDate: " +resourceDate.toString()+"\n";


        } else {
            return("Unable to load jar:" + jarFilename+ "  \nUrl: " +resourceUrl);

        }
    } catch (Exception e){
        return e.getMessage();
    }


}

위의 코드는 경로에서 모든 리소스를 찾습니다. 항아리 안에 항아리가있을 경우 항아리의 크기와 날짜, 항아리 안의 자원의 크기와 날짜
Don
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.