코드 동적 생 성 이기 ASM

코드 동적 생 성 이기 ASM
저자:설 곡 우
저자 소개
설 곡 우,NORDSAN(베 이 징)정보 과학기술 개발 유한 공사 고급 JAVA 연구 개발 엔지니어,기업 급 이색 데이터 교환 서버 제품 의 연구 개발 에 힘 쓰 고 있 습 니 다.J2EE 와 WEB SERVICE 분야 에서 비교적 풍부 한 개발 경험 을 가지 고 있 습 니 다[email protected]그 와 연락 하 다.
머리말
코드 생 성기(code generator,CG)는 말 그대로 코드 를 만 드 는 도구 다.그것 이 있 으 면 간단 한 설정 이나 데이터 베이스 디자인 에서 수백,수천 줄 의 코드 를 얻 을 수 있다.이 기술 을 사용 하지 않 으 면 개발 자 는 몇 시간 이나 며칠 동안 이 코드 를 손 으로 작성 해 야 합 니 다.다른 한편,우수한 개발 도 구 는 독특한 기능 을 제공 하거나 오류 가 발생 하기 쉬 운 세부 사항 을 차단 하기 위해 코드 생 성 기술 로 사용자 에 게 프로그램의 템 플 릿 구 조 를 제공 하 는데 그 목적 도 프로 그래 밍 의 효율 을 높이 기 위해 서 이다.이상 의 관점 은 코드 생 성기 에 대한 일반적인 이해 일 뿐이다.다시 말 하면 이것 은 있어 도 되 고 없어 도 되 는 것 같 고 그것 이 없 으 면 인공 을 좀 더 많이 쓰 는 것 에 불과 하 다.그러나 본 고 에서 소개 하고 자 하 는 이 ASM 이라는 JAVA 도구 류 의 기능 은 예 사 롭 지 않다.이것 은 JAVA 바이트 코드,즉 class 파일 을 생 성 할 수 있다.응용 프로그램 에서 상황 에 따라 다양한 클 라 스 를 동적 으로 생 성 한 다음 에 호출 하여 하나님 의 조물 에 가 까 운 신기 함 을 이 룰 수 있 습 니 다.설 레 는 것 은 행동 보다 못 하 다.자신의 개발 에 앞서 가 는 프로 그래 밍 기술 을 도입 하고 싶다 면 이 글 을 보 세 요.
작고 신기 한 ASM.
ASM 은 JAVA 바이트 코드 생 성 구조 입 니 다.바 이 너 리 형식의 stub 클래스 나 다른 프 록 시 클래스 를 동적 으로 생 성하 거나 JAVA 가상 컴퓨터 에 메모리 가 불 러 오기 전에 동적 수정 클래스 를 생 성 할 수 있 습 니 다.ASM 은 BCEL(http://jakarta.apache.org/bcel )와 SERP(http://serp.sourceforge.net/ )비슷 한 기능 은 22K 크기 로 350 K 의 BCEL 과 150 K 의 SERP 에 비해 상당히 작고 집행 효율 이 높 으 며 BCEL 의 7 배,SERP 의 11 배 이상이다.ASM 의 일 관 된 디자인 사상 은 바로 이 를 동적 생 성 분야 에 응용 하 는 것 이기 때문에 작고 빠 른 것 은 이 제품 의 디자인 과 실현 에 대한 지도 사상 이다.
이 제품 은 프랑스 텔 레 콤 의 연구개 발 엔지니어 에 릭 브 루 넷 이 맡 았 다.2002 년 7 월 ASM 의 첫 번 째 버 전이 발 표 된 이래 지금까지 이 제품 은 이미 다섯 차례 업그레이드 되 어 나날이 완벽 해 지고 있다.지금까지 ASM 의 최신 버 전 은 1.3.5 입 니 다.가 셔 도 됩 니 다.http://asm.objectweb.org/ 다운로드
ASM 의 최종 목 표 는 생 성 도 구 를 만 드 는 것 입 니 다.모든 종류의 처리 작업 을 수행 할 수 있 습 니 다.(일부 도구,예 를 들 어 자바 ssit 와 달리 미리 정 의 된 클래스 작업 만 지원 하지만 많은 경우 에 이러한 기능 은 한계 가 있 습 니 다)
JAVA 의 CLASS 파일 형식
ASM 을 다 루 려 면 JAVA 의 CLASS 파일 형식 부터 알 아 봐 야 합 니 다.JAVA 의 CLASS 파일 은 보통 트 리 구조 입 니 다.루트 노드 는 다음 과 같은 요 소 를 포함 합 니 다:
ConstantPool:기호 표;
  • FieldInfo:클래스 의 구성원 변수 정보;
  • MethodInfo:클래스 의 방법 설명;
  • Attribute:선택 할 수 있 는 추가 노드.

  • FieldInfo 노드 는 Public,private,static 등 구성원 변수의 이름 을 포함 합 니 다.ConstantValue 속성 은 정적 으로 변 하지 않 는 구성원 변수의 값 을 저장 하 는 데 사 용 됩 니 다.Deprecated 와 Synthetic 는 구성원 변 수 를 추천 하지 않 거나 컴 파일 러 에 의 해 생 성 되 었 음 을 표시 하 는 데 사 용 됩 니 다.
    MethodInfo 노드 는 방법의 이름,매개 변수의 유형 과 그 반환 값 을 포함 하고 방법 은 공유 적 이 고 개인 적 이거 나 정적 인 표지 입 니 다.MethodInfo 는 선택 할 수 있 는 추가 속성 을 포함 하 는데 그 중에서 가장 중요 한 것 은 Code 속성 이 고 추상 적 이지 않 은 방법의 코드 를 포함한다.Exceptions 속성 은 던 질 Exception 의 이름 을 포함 합 니 다.Deprecated 와 Synthetic 속성의 정 보 는 위의 FieldInfo 의 정의 와 같 습 니 다.
    루트 노드 의 선택 가능 한 속성 은 SourceFile,InnerClasses,Deprecated 가 있 습 니 다.SourceFile 은 바이트 코드 로 컴 파일 된 소스 코드 파일 의 원본 이름 을 저장 하 는 데 사 용 됩 니 다.InnerClasses 는 내부 클래스 의 정 보 를 저장 합 니 다.이러한 속성 이 존재 하기 때문에 자바 의 클래스 형식 은 확장 할 수 있 습 니 다.즉,하나의 class 에 표준 이 아 닌 속성 을 추가 할 수 있 습 니 다.자바 가상 기 회 는 이러한 식별 할 수 없 는 속성 을 무시 하고 이 class 를 정상적으로 불 러 옵 니 다.
    ConstantPool 은 숫자 나 문자열 상수 의 색인 으로 구 성 된 대기 열 또는 이러한 트 리 의 다른 노드 가 참조 하여 다른 대상 이 만 든 상수 의 색인 으로 구 성 된 대기 열 입 니 다.이 표 의 목 표 는 번 거 로 움 을 줄 이기 위 한 것 이다.예 를 들 어 FieldInfo 노드 는 노드 의 이름 을 포함 하지 않 고 이 표 에 있 는 색인 만 포함 합 니 다.마찬가지 로 GETFIELD 와 PUTFIELD 는 구성원 변수의 이름 을 직접 포함 하지 않 고 이름 의 색인 만 포함 합 니 다.
    ASM 에 정통 하 다
    Asm 구 조 는 전체적으로 두 개의 인 터 페 이 스 를 둘러싸 고 있 습 니 다.즉,ClassVisitor 와 CodeVisitor 는 모든 종류의 방법,구성원 변 수 를 방문 할 수 있 고 모든 방법 에 포 함 된 바이트 코드 명령 을 포함 합 니 다.classReader 는 class 파일 을 읽 는 데 사 용 됩 니 다.ClassWriter 클래스 는 생 성 된 Class 파일 을 쓰 는 데 사 용 됩 니 다.
    존재 하 는 class 를 수정 하기 위해 서 는 class 파일 을 분석 하 는 ClassReader,클래스 의 수정 기와 class 파일 을 쓰 는 ClassWriter 를 사용 해 야 합 니 다.클래스 의 수정 기 는 ClassVisitor 입 니 다.일부 작업 을 다른 ClassVisitor 에 위임 할 수 있 지만 예상 되 는 수정 절 차 를 실현 하기 위해 일부 매개 변수의 값 을 바 꾸 거나 다른 방법 을 호출 할 것 입 니 다.이러한 종류의 수정 기 를 비교적 쉽게 실현 하기 위해 ASM 은 ClassAdapter 와 CodeAdapter 를 제 공 했 는데 이 두 어댑터 류 는 각각 ClassVistor 와 CodeVistor 인 터 페 이 스 를 실현 했다.
    Hello World,창조 의 신기 함 체험
    다음은 ASM 동적 으로 바이트 코드 를 생 성 하 는 클래스 를 적용 하고 그 방법의 완전한 HelloWorld 프로그램 을 호출 합 니 다.프로그램의 기능 은 example.class 클래스 를 동적 으로 생 성하 고 example 대상 을 실례 화하 여 대상 의 main 함 수 를 호출 하여 화면 에"Hello World!"를 인쇄 하 는 것 입 니 다.
    import org.objectweb.asm.*;
    import java.lang.reflect.*;
    import java.io.FileOutputStream;
    
    public class Helloworld extends ClassLoader implements Constants {
    
      public static void main (final String args[]) throws Exception {
    
        /*
         *         class,   java    :
         *
         * public class Example {
         *   public static void main (String[] args) {
         *     System.out.println("Hello world!");
         *   }
         * }
         *
         */
    
        //     ClassWriter
        ClassWriter cw = new ClassWriter(false);
        cw.visit(ACC_PUBLIC, "Example", "java/lang/Object", null, null);
    
        //      MethodWriter
        CodeVisitor mw = cw.visitMethod(ACC_PUBLIC, "
          
           ", "()V", null);
        //    'this'   
        mw.visitVarInsn(ALOAD, 0);
        //           
        mw.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "
           
            ", "()V"); mw.visitInsn(RETURN); //                      mw.visitMaxs(1, 1); //  main      MethodWriter mw = cw.visitMethod( ACC_PUBLIC + ACC_STATIC, "main", "([Ljava/lang/String;)V", null); //   System  out    mw.visitFieldInsn( GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;"); // pushes the "Hello World!" String constant mw.visitLdcInsn("Hello world!"); //   System.out 'println'    mw.visitMethodInsn( INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V"); mw.visitInsn(RETURN); //                      mw.visitMaxs(2, 2); //           byte[] code = cw.toByteArray(); FileOutputStream fos = new FileOutputStream("Example.class"); //    fos.write(code); //      fos.close(); //          Helloworld loader = new Helloworld(); Class exampleClass = loader.defineClass("Example", code, 0, code.length); //            'Helloworld' Method main = exampleClass.getMethods()[0]; main.invoke(null, new Object[] {null}); } } 
           
          

    좋은 웹페이지 즐겨찾기