초기 자바 클래스 로드 메커니즘

1.jdk 1.2 이후 클래스 로 딩 은 의뢰 를 통 해 이 루어 집 니 다.이 는 ClassLoader 가 클래스 를 찾 지 못 하면 부모 대 ClassLoader 에 게 이 작업 을 수행 하 라 고 요청 합 니 다.모든 ClassLoaders 의 뿌리 는 시스템 ClassLoader 입 니 다.이 는 결 성 된 방식 으로 클래스 를 불 러 옵 니 다.즉,이 파일 시스템 에서.오늘 우 리 는 jvm 에서 이 메커니즘 들 이 어떻게 운행 되 는 지 연구 해 보 자.class 바이트 파일(예 를 들 어 Hello.class 파일)이 있다 고 가정 합 시다.그러면 응용 프로그램 에서 그 는 어떻게 불 러 와 하나의 대상 을 만 들 었 습 니까?우리 의 이 문장의 목적 은 바로 이 문 제 를 해석 하기 위 한 것 이다.java.lang 패키지 에 ClassLoader 클래스 가 있 습 니 다.ClassLoader 의 기본 목 표 는 클래스 요청 에 서 비 스 를 제공 하 는 것 입 니 다.JVM 이 클래스 를 사용 해 야 할 때 이름 에 따라 ClassLoader 에 이 클래스 를 요청 한 다음 ClassLoader 는 이 클래스 를 표시 하 는 Class 대상 을 되 돌려 주 려 고 합 니 다.이 과정 에 대응 하 는 단계별 방법 을 덮어 쓰 면 맞 춤 형 ClassLoader 를 만 들 수 있 습 니 다.그 중에서 loadclass(String name,boolean resolve)방법 이 있 습 니 다.이 방법 은 ClassLoader 의 입구 점 입 니 다.jdk 1.2 이후 loadclass 방법 은 findClass 방법 을 사용 하지 않 습 니 다.자세 한 내용 은 API 문 서 를 참고 할 수 있 습 니 다.저희 가 작성 한 ClassLoader 는 주로 상기 두 가지 방법 을 덮어 쓰기 위해 서 입 니 다.우리 가 방금 한 문제 로 돌아 가 바이트 코드 파일 을 어떻게 읽 고 그것 을 하나의 대상 으로 구성 합 니까?ClassLoader 에 방법 이 있 습 니 다.Class defineClass(String name,by te[]b,int off,int len)는 답 이 여기 있 습 니 다.우 리 는 class 바이트 파일(예 를 들 어 Hello.class)을 한 바이트 배열 에 읽 고 by te[]b 를 Class 대상 으로 바 꿀 수 있 습 니 다.이 데 이 터 는 파일,네트워크 등에 서 유래 할 수 있 습 니 다.신기 하 죠?)defineClass 는 JVM 의 많은 복잡 함 을 관리 합 니 다.신비 와 실현 에 의존 하 는 측면-바이트 코드 를 실행 시 데이터 구조,검증 유효성 등 으로 분석 합 니 다.걱정 하지 마 세 요.직접 작성 하 실 필 요 는 없습니다.사실,당신 이 이렇게 하려 고 해도 그것 을 덮어 쓸 수 없습니다.왜냐하면 그것 은 이미 최종 적 으로 표시 되 었 기 때 문 입 니 다.다른 방법:findSystem Class 방법:로 컬 파일 시스템 에서 파일 을 불 러 옵 니 다.로 컬 파일 시스템 에서 클래스 파일 을 찾 습 니 다.존재 하면 defineClass 를 사용 하여 원본 바이트 를 Class 대상 으로 변환 하여 클래스 로 변환 합 니 다.findClass 방법:jdk 1.2 이후 loadClass 의 부족 으로 이 새로운 방법 을 호출 합 니 다.findClass 의 용 도 는 ClassLoader 의 모든 특수 코드 를 포함 하고 다른 코드 를 복사 할 필요 가 없습니다(예 를 들 어 전문 적 인 방법 이 실 패 했 을 때 시스템 ClassLoader 를 호출 합 니 다).getSystemClassLoader:findClass 나 loadClass 를 덮어 쓰 면 getSystemClassLoader 는 실제 ClassLoader 대상 으로 시스템 ClassLoader 에 접근 할 수 있 습 니 다.getParent:클래스 요청 을 부모 대 ClassLoader 에 의뢰 하기 위해 서,이 새로운 방법 은 ClassLoader 가 부모 대 ClassLoader 를 가 져 올 수 있 도록 합 니 다.특수 한 방법 을 사용 하면 맞 춤 형 ClassLoader 에서 클래스 를 찾 을 수 없 을 때 이 방법 을 사용 할 수 있 습 니 다.resolve Class:클래스 를 불완전 하 게 불 러 올 수도 있 고,클래스 를 완전히 불 러 올 수도 있 습 니 다.우리 자신의 loadClass 를 작성 할 때 resolveClass 를 호출 할 수 있 습 니 다.이것 은 loadClass 의 resolve 매개 변수 값 에 달 려 있 습 니 다.findLoaded Class:캐 시 역할 을 합 니 다.loadClass 에 클래스 를 불 러 오 라 고 요청 할 때 이 방법 을 사용 하여 ClassLoader 가 이 클래스 를 불 러 왔 는 지 확인 합 니 다.존재 하 는 클래스 를 다시 불 러 오 는 데 발생 하 는 번 거 로 움 을 피 할 수 있 습 니 다.우선 이 방법 을 호출 해 야 한다.2.작업 절차:1)findLoadedClass(String)를 호출 하여 불 러 온 클래스 가 있 는 지 확인 합 니 다.없 으 면 특별한 신기 한 방식 으로 원본 바이트 를 가 져 옵 니 다.2)부모 클래스 ClassLoader 를 통 해 loadclass 방법 을 호출 합 니 다.부모 클래스 ClassLoader 가 null 이면 결 성 된 방식 으로 클래스,즉 시스템 ClassLoader 를 불 러 옵 니 다.3)findClass(String)를 호출 하여 클래스 를 찾 고 가 져 오기;4)loadClass 의 resolve 매개 변수 값 이 true 라면 resolve Class 를 호출 하여 Class 대상 을 분석 합 니 다.5)클래스 가 없 으 면 ClassNotFoundException 으로 돌아 갑 니 다.6)그렇지 않 으 면 호출 프로그램 에 클래스 를 되 돌려 줍 니 다.3.ClassLoader 를 실현 한 예:/**Compiling ClassLoader.java*Copyright 2005-2-12*/import java.io.*;public class Compiling ClassLoader extends ClassLoader{/파일 의 내용 을 읽 습 니 다 private byte[]getBytes(String filename)throws IOException{File file=new File(filename);  long len=file.length();   byte[] raw=new byte[(int)len];   FileInputStream fin=new FileInputStream(file);   int r=fin.read;   if(r!=len) throw new IOException("Can't read all,"+r+"!="+len);   fin.close();   return raw;   }   private boolean compile(String javaFile) throws IOException{   System.out.println("CCL:Compiling "+javaFile+"..."); //호출 시스템 의 javac 명령 Process p=Runtime.getRuntime().exec("javac"+javaFile);try{//다른 스 레 드 는 이 스 레 드 가 완성 되 기 를 기다 리 고 있 습 니 다.p.waitFor();  }catch(InterruptedException ie){   System.out.println(ie);   }   int ret=p.exitValue();   return ret==0;   }   public Class loadClass(String name,boolean resovle) throws ClassNotFoundException{   Class clas=null;   clas=findLoadedClass(name); //가방 의 표시 String fileStub=name.replace(','/')를 설명 합 니 다.  String javaFilename=fileStub+".java";   String classFilename=fileStub+".class";   File javaFile=new File(javaFilename);   File classFile=new File(classFilename); //class 파일 이 존재 하면 if(javaFile.exists()&&(!classFile.exists()||javaFile.lastModified()>classFile.lastModified())){   try{    if(!compile(javaFilename)||!classFile.exists()){     throw new ClassNotFoundException("ClassNotFoundExcetpion:"+javaFilename);    }   }catch(IOException ie){    throw new ClassNotFoundException(ie.toString());   }   }   try{   byte[] raw=getBytes(classFilename); //데 이 터 를 읽 어서 클래스 구 조 를 구성 합 니 다.이것 은 핵심 clas=defineClass(name,raw,0,raw.length)입 니 다.  }catch(IOException ie){   //   }   if(clas==null){   clas=findSystemClass(name);   }   System.out.println("findSystemClass:"+clas);   if(resovle && clas!=null){   resolveClass(clas);   }   if(clas==null){   throw new ClassNotFoundException(name);   }   return clas; }}이 로 더 를 테스트 합 니 다:/***TestRun.java*Copyright 2005-2-11*/import java.lang.reflect.*;  public class TestRun{   public static void main(String[] args) throws Exception{   String progClass=args[0];   String progArgs[]=new String[args.length-1];   System.arraycopy(args,1,progArgs,0,progArgs.length);   CompilingClassLoader ccl=new CompilingClassLoader();   Class clas=ccl.loadClass(progClass); //class 의 type class[]mainArgType={(new String[0]).getClass()}를 되 돌려 줍 니 다.  Method main=clas.getMethod("main",mainArgType);   Object argsArray[]={progArgs};   main.invoke(null,argsArray); }}이상 의 핵심 내용 을 작 성 했 습 니 다.컴 파일 한 후에 우 리 는 두 개의 파일 을 얻 었 습 니 다.Compiling ClassLoader.class,TestRun.class 4.예 를 들 어 우리 의 ClassLoader/**Hello.java*/public class Hello{public static void main(String[]args){if(args.length!=1){    System.err.println("Error,exit!");    System.exit(1);   }   String name=args[0];   System.out.println("Hello,"+name); }자,자바 TestRun Hello 아비 실행........Hello,아비 실행

좋은 웹페이지 즐겨찾기