Determine which JAR file a class is from
I am not in front of an IDE right now, just looking at the API specs.
CodeSource src = MyClass.class.getProtectionDomain().getCodeSource();
if (src != null) {
URL jar = src.getLocation();
}
I want to determine which JAR file a class is from. Is this the way to do it?
Yes. It works for all classes except classes loaded by bootstrap classloader. The other way to determine is:
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
체크아웃LiveInjector.findPathJar()
롬복 패처로부터. 파일이 실제로 항아리 안에 살지 않는 특별한 경우라는 점에 유의하십시오. 그리고 당신은 그것을 바꾸고 싶을지도 모른다.
/**
* 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.");
}
}
Use
String path = <Any of your class within the jar>.class.getProtectionDomain().getCodeSource().getLocation().getPath();
If this contains multiple entries then do some substring operation.
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();
}
}
Linux에서는 작은 스크립트를 사용하여 클래스가 어느 항아리에 있는지 찾을 수 있도록 도와주고 있다.find -exec
:
findclass.sh
:
unzip -l "$1" 2>/dev/null | grep $2 >/dev/null 2>&1 && echo "$1"
기본적으로, 항아리가 지퍼로 되어 있기 때문에unzip -l
클래스 리소스 목록을 인쇄하므로 변환하십시오..
로/
. 스크립트에서 대체를 수행할 수 있는 경우tr
, 하지만 대본에 전화할 때 직접 하는 것은 그리 어려운 일이 아니다.
그 아이디어는find
모든 항아리를 찾기 위한 수업 경로의 뿌리에 있는findclass.sh
성냥을 찾기 위해 발견된 모든 항아리들 위에
It doesn't handle multi-directories, but if you carefully choose the root you can get it to work.
이제 클래스가 들어 있는 항아리를 찾으십시오.org.apache.commons.lang3.RandomUtils
프로젝트 관리(...):
$ find ~/.m2/repository/ -type f -name '*.jar' -exec findclass.sh {} org/apache/commons/lang3/RandomUtils \;
.m2/repository/org/apache/commons/commons-lang3/3.7/commons-lang3-3.7.jar
.m2/repository/org/apache/commons/commons-lang3/3.6/commons-lang3-3.6.jar
.m2/repository/org/apache/commons/commons-lang3/3.6/commons-lang3-3.6-sources.jar
$
ReferenceURL : https://stackoverflow.com/questions/1983839/determine-which-jar-file-a-class-is-from
'Programing' 카테고리의 다른 글
JFrame을 프로그래밍 방식으로 닫는 방법 (0) | 2022.05.09 |
---|---|
다중 모듈 maven 프로젝트에서 모듈 간에 src/테스트 클래스 공유 (0) | 2022.05.09 |
VueJS는 프로덕션 모드에서 빌드된 경우에도 "개발 모드" 메시지를 표시함 (0) | 2022.05.09 |
충돌 @Dragenter @Dragleave / v-show 이벤트가 계속 빠르게 발생함 (0) | 2022.05.09 |
IntelliJ IDEA 13은 1.7로 설정되었음에도 불구하고 Java 1.5를 사용한다. (0) | 2022.05.09 |