[위 에] URLClassLoader 를 사용 하여 외부 jar 패키지 의 자바 류 를 불 러 와 Class 파일 을 생 성 합 니 다.
12944 단어 자바ClassLoaderClass
//****************************
많은 경우 에 우리 가 쓴 자바 프로그램 은 모듈 로 나 뉘 어 져 있 습 니 다. 아주 좋 은 확장 메커니즘 이 있 습 니 다. 즉, 우 리 는 우리 자신의 자바 류 에 플러그 인 을 추가 하여 미래 에 우리 가 개발 할 수 있 는 종 류 를 실행 할 수 있 습 니 다. 아래 에 이러한 종 류 를 플러그 인 류 라 고 부 릅 니 다.
다음은 간단 한 실현 방법 이다.
Class A 는 프로그램의 주 입구 로 서 프로그램의 실행 입구 (main) 함 수 를 포함 합 니 다.그리고 main 함수 에서 외부 프로필 을 통 해 외부 프로필 을 통 해 플러그 인 류 의 정보 (어느 jar 패키지, jar 패키지 의 구체 적 인 경로 에 있 는 지) 를 얻 은 다음 jar 패키지 의 특정한 인 스 턴 스 를 얻어 해당 하 는 작업 을 수행 할 수 있 습 니 다.이 jar 가방 은 외부 jar 가방 일 가능성 이 높 습 니 다. 우리 가 직접 쓴 것 입 니 다. 그러면 우 리 는 어디 에 두 어야 그 가 스스로 찾 을 수 있 습 니까?구체 적 인 디 렉 터 리 를 class 에 넣 지 않 는 한 여러 번 시도 해 봤 습 니 다.path 에서 만 성공 적 으로 실행 할 수 있 습 니 다. 그렇지 않 으 면 이상 을 보고 하 는 것 은 하나의 Class NotFoundation Exception 일 뿐 종 류 를 찾 을 수 없습니다.하지만 이 jar 패 키 지 를 jar 패 키 지 를 실행 하 는 디 렉 터 리 에 압축 을 풀 면 classpath 의.. 해당 클래스 를 얻 을 수 있 습 니 다.하지만 이렇게 하면 프로 답지 못 해 보 입 니 다. 자바 가 쓴 것 은 모두 jar 가방 입 니 다. 자신 이 느끼 는 것 입 니 다.claspath 에 넣 으 면 새로운 jar 가방 을 쓸 때마다 설정 할 수 는 없 잖 아 요!
이렇게 해서 다음 과 같은 해결 방법 이 나 타 났 다.
해결 방법의 의 미 를 알 고 싶 으 면 먼저 자바 의 클래스 로드 체 제 를 알 아야 합 니 다.프로그램 이 실행 되 려 면 메모리 에 불 러 와 야 성공 적 으로 실 행 될 수 있다 는 것 은 잘 알려 져 있다.자바 프로그램 은 실행 가능 한 파일 이 아니 라 많은 독립 된 클래스 파일 로 이 루어 집 니 다.그래서 자바 에서 불 러 오 는 프로그램 은 클래스 를 하나의 외부 로 완성 합 니 다.이것 도 자바 의 class loader 로 딩 메커니즘 을 간단하게 알 아 봐 야 합 니 다.
자바 프로그램 이 실행 되 기 시 작 했 습 니 다. 첫 번 째 classloader 는 boottstrap classloader 입 니 다. 이 classloader 는 c + 언어 로 작성 되 었 습 니 다. 그 를 통 해 자바 의 핵심 클래스 를 불 러 옵 니 다.두 번 째 classloader 는 extension classloader 입 니 다. jre / lib 디 렉 터 리 의 ext 디 렉 터 리 에 있 는 jar 패 키 지 를 불 러 옵 니 다.그 다음 에 세 번 째 는 system classloader 이 고 응용 로 더 라 고도 불 리 며 주로 로 딩 - classpath 또는 시스템 의 전체 변수 인 ClassPath 의 클래스 를 완성 합 니 다.System.out.println(System.getProperty(“java.class.path”));classpath 설정 을 얻 을 수 있 습 니 다. 즉, system classloader 가 불 러 오 는 클래스 입 니 다. 네 번 째 classloader 는 사용자 정의 로 딩 클래스 일 수 있 습 니 다.일반적으로 하나의 종류의 로드 과정 은 현재 클래스 로 더 의 부모 로 더 를 통 해 찾 으 려 고 시도 합 니 다. 부모 로 더 를 찾 지 않 으 면 최종 boottstrap classloader 까지 불 러 오 려 고 시도 합 니 다. 찾 지 못 하면 위 에서 아래로 클래스 를 불 러 옵 니 다.이렇게 하 는 목적 은 사용자 정의 클래스 가 시스템 의 클래스 를 덮어 쓰 는 것 을 방지 하 는 것 입 니 다. 이러한 메커니즘 이 없 으 면 이런 농담 이 쉽게 발생 할 수 있 습 니 다. 자신 이 String 류 를 쓴 다음 에 new string 은 자신 이 쓴 String 류 입 니 다. 그러면 비교적 재 미 있 습 니 다.
//*********************************************
다음은 제 가 최근 에 프로젝트 를 한 실제 코드 입 니 다. 참고 할 수 있 습 니 다.
1. URLClassLoader 대상 을 정의 하여 외부 jar 패 키 지 를 불 러 옵 니 다. jar 패 키 지 는 더 이상 jar 패키지 가 나타 나 지 않 습 니 다. 즉, 'class 파일 만 분석 합 니 다:
private static void test1() {
String path = "D:\\test.jar";// jar
Set<Class<?>> classes = new LinkedHashSet<Class<?>>();// Class
Map<Class<?>, Annotation[]> classAnnotationMap = new HashMap<Class<?>, Annotation[]>();// Class
Map<Class<?>, Map<Method, Annotation[]>> classMethodAnnoMap = new HashMap<Class<?>, Map<Method,Annotation[]>>();// Class
try {
JarFile jarFile = new JarFile(new File(path));
URL url = new URL("file:" + path);
ClassLoader loader = new URLClassLoader(new URL[]{url});// classLoader , load , load
Enumeration<JarEntry> es = jarFile.entries();
while (es.hasMoreElements()) {
JarEntry jarEntry = (JarEntry) es.nextElement();
String name = jarEntry.getName();
if(name != null && name.endsWith(".class")){// .class , jar
// , jar
//Class<?> c = Thread.currentThread().getContextClassLoader().loadClass(name.replace("/", ".").substring(0,name.length() - 6));
Class<?> c = loader.loadClass(name.replace("/", ".").substring(0,name.length() - 6));// loader
System.out.println(c);
classes.add(c);
Annotation[] classAnnos = c.getDeclaredAnnotations();
classAnnotationMap.put(c, classAnnos);
Method[] classMethods = c.getDeclaredMethods();
Map<Method, Annotation[]> methodAnnoMap = new HashMap<Method, Annotation[]>();
for(int i = 0;i<classMethods.length;i++){
Annotation[] a = classMethods[i].getDeclaredAnnotations();
methodAnnoMap.put(classMethods[i], a);
}
classMethodAnnoMap.put(c, methodAnnoMap);
}
}
System.out.println(classes.size());
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
이상 의 경우 다른 procject 프로젝트 에 test 방법 을 쓸 수 있 습 니 다. 평소에 가장 많이 사용 되 는 것 입 니 다. class 파일 에 다른 jar 가방 에 의존 하 는 대상 이 있 을 때 이 jar 가방 을 이 테스트 방법 을 쓰 는 procject 와 buildPath 로 복사 해 야 합 니 다. 그렇지 않 으 면 실 행 될 때 Class 대상 의 이상 을 찾 을 수 없습니다.
2. 두 번 째 상황 은 jar 가방 에 있 는 jar 가방 을 불 러 오 는 Class 대상 과 특정한 properties 파일 을 읽 는 방법 입 니 다.
private static void test2() {
String path = "D:\\test.jar";// jar jar
try {
JarFile jarfile = new JarFile(new File(path));
Enumeration<JarEntry> es = jarfile.entries();
while (es.hasMoreElements()) {
JarEntry je = es.nextElement();
String name = je.getName();
if(name.endsWith(".jar")){// jar jar
File f = new File(name);
JarFile j = new JarFile(f);
Enumeration<JarEntry> e = j.entries();
while (e.hasMoreElements()) {
JarEntry jarEntry = (JarEntry) e.nextElement();
System.out.println(jarEntry.getName());
//.........
}
}
// System.out.println(je.getName());
if(je.getName().equals("entity_pk.properties")){
InputStream inputStream = jarfile.getInputStream(je);
Properties properties = new Properties();
properties.load(inputStream);
Iterator<Object> ite = properties.keySet().iterator();
while (ite.hasNext()) {
Object key = ite.next();
System.out.println(key + " : " +properties.get(key));
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
3. 세 번 째 상황 은 이 항목 에서 가방 의 Class 대상 을 가 져 오 는 것 입 니 다. 물론 테스트 방법 은 이 항목 에 적 혀 있 습 니 다. (이렇게 하면 classLoader 는 대상 을 직접 알 수 있 습 니 다. URLClassLoader 를 사용자 정의 할 필요 가 없습니다. Thread. current Thread (). getContextClassLoader (). loadclass (...)Class 대상 을 직접 얻 을 수 있 습 니 다. ClassPath 에서 찾 아 보 세 요. System. out. print (System. getProperty ("java. class. path") 에서 classPath 경 로 를 찾 을 수 있 습 니 다.
private static Set<Class<?>> getclass() {
Set<Class<?>> classes = new LinkedHashSet<Class<?>>();
boolean flag = true;//
String packName = "com.yk.framework.db";
// String packName = "org.jdom";
String packDir = packName.replace(".", "/");
Enumeration<URL> dir;
try {
dir = Thread.currentThread().getContextClassLoader().getResources(packDir);
while(dir.hasMoreElements()){
URL url = dir.nextElement();
System.out.println("url:***" + url);
String protocol = url.getProtocol();//
if("file".equals(protocol)){
System.err.println("file ");
String filePath = URLDecoder.decode(url.getFile(), "UTF-8");
System.out.println("filePath :" + filePath);
findAndAddClassesInPackageByFile(packName, filePath,flag,classes);
}else if("jar".equals(protocol)){
System.err.println("jar ");
JarFile jar;
jar = ((JarURLConnection)url.openConnection()).getJarFile();
Enumeration<JarEntry> entries = jar.entries();
while(entries.hasMoreElements()){
JarEntry entry = entries.nextElement();
String name = entry.getName();
System.out.println(">>>>:" + name);
//......
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
System.out.println(classes.size());
return classes;
}
아래 위의 두 번 째 코드
private static void findAndAddClassesInPackageByFile(String packName, String filePath, final boolean flag, Set<Class<?>> classes) {
File dir = new File(filePath);
if( !dir.exists() || !dir.isDirectory()){
System.out.println(" ");
return;
}
File[] dirfiles = dir.listFiles(new FileFilter(){
@Override
public boolean accept(File pathname) {
return flag && pathname.isDirectory() || pathname.getName().endsWith(".class");
}
});
for (File file : dirfiles) {
if(file.isDirectory()){// ,
findAndAddClassesInPackageByFile(packName + "." + file.getName(),file.getAbsolutePath(),flag,classes);
}else{//
String className = file.getName().substring(0,file.getName().length() - 6);
System.out.println(" :" +className);
try {
classes.add(Thread.currentThread().getContextClassLoader().loadClass(packName + "." + className));
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
}
자, 대체로 그렇습니다. 열심히 공부 하고 매일 향상 하 세 요!하하 ~ ~
보충:
4. jar 패키지 의 enity 읽 기pk. properties 키 값 이 프로젝트 로 컬 enitypk. properties 파일 중
/**
* jar entity_pk.properties entity_pk.properties
*/
private static void test2() {
String path = "D:\\test.jar";
try {
JarFile jarFile = new JarFile(new File(path));
Enumeration<JarEntry> es = jarFile.entries();
while (es.hasMoreElements()) {
JarEntry jarEntry = (JarEntry) es.nextElement();
String name = jarEntry.getName();
if(name.equals("entity_pk.properties")){
InputStream inputStream = new FileInputStream(name);
Properties prop = new Properties();
prop.load(inputStream);// load entity_pk.propertoes
InputStream inputStream2 = jarFile.getInputStream(jarEntry);// jar entity_pk.propertoes
Properties prop2 = new Properties();
prop2.load(inputStream2);
Enumeration<Object> ks = prop2.keys();
OutputStream out = new FileOutputStream(name);
while (ks.hasMoreElements()) {
String key = (String)ks.nextElement();
System.out.println(key + " : " +prop2.getProperty(key));
prop.setProperty(key, prop2.getProperty(key));// jar entity_pk.properties
}
prop.store(out,"");
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
5. 읽 기와 쓰기 dbconfig. xml 파일
/**
* db_config.xml
*/
private static void test3() {
String path = "D:\\test.jar";
try {
JarFile jarFile = new JarFile(new File(path));
Enumeration<JarEntry> es = jarFile.entries();
while (es.hasMoreElements()) {
JarEntry jarEntry = (JarEntry) es.nextElement();
String name = jarEntry.getName();
if(name.equals("db_config.xml")){
InputStream inputStream = jarFile.getInputStream(jarEntry);
SAXBuilder builder = new SAXBuilder();
Document doc = null;
try {
doc = builder.build(inputStream);
if(doc != null){
Element e = doc.getRootElement();
Element proxool = e.getChild("proxool");
List<Element> children = proxool.getChildren();
for (Element element : children) {
System.out.println(element.getText());
}
Element s = new Element("test");
s.addContent("test");
proxool.addContent(s);
XMLOutputter outputter = new XMLOutputter();
outputter.output(doc, new FileOutputStream("config/db_config.xml"));
}
} catch (JDOMException e) {
e.printStackTrace();
}finally{
if(inputStream != null){
inputStream.close();
}
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Is Eclipse IDE dying?In 2014 the Eclipse IDE is the leading development environment for Java with a market share of approximately 65%. but ac...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.