본문 바로가기

java

[Java] 컴파일된 클래스 내에서의 메소드 개요 컴파일된 클래스에서 메소드는 일련의 바이트코드 인스트럭션들로 저장되어 있다.따라서, 메소드를 변환하거나 생성하기 위해서는 바이트코드 인스트럭션이 어떤 것이고 어떻게 동작하는 지 이해하는 것이 필요하다. 자세한 이해는 JVM 스펙을 참고하고, 여기서는 간단한 변환이나 생성 코딩에 필요한 정도로만 알아보자. 바이트코드 인스트럭션을 이해가기 위해서는 우선 JVM 머신의 실행 모델에 대해 이해할 필요가 있다.자바 코드는 스레드에서 실행되는데, 각각의 스레드는 실행 스택을 가지며, 이는 프레임들로 구성된다. 각각의 프레임은 어떤 하나의 메소드 실행을 나타낸다. 프레임은 두 부분으로 구성된다.로컬 변수 파트랜덤 억세스가 가능한 인덱스를 가지는 변수들로 구성오퍼랜드 스택바이트코드 인스트럭션이 사용할 오퍼랜드 스택St.. 더보기
[Java] ASM Textifier ASM 5 에서 제공하는 유틸리티 클래스이다. .class 파일을 인자로 받아서 바이트코드를 읽을 수 있는 코드로 변환해 출력해준다. 사용법 이전에 만들었던 HelloWorld를 출력한 결과 더보기
[Java] ASM을 이용한 클래스 멤버 추가 클래스에 필드를 추가하는 경우를 생각해 보자. visit visitSource? visitOuterClass? ( visitAnnotation | visitAttribute )*( visitInnerClass | visitField | visitMethod )*visitEnd 위의 ClassVisitor 클래스의 메소드 호출 순서를 염두에 두면, 추가를 위해 선택 가능한 메소드는 visitInnerClass, visitField, visitMethod, visitEnd 이다. 만약, visit 메소드에서 추가했다고 하면 visitField 호출 후에 visitSource, visitOuterClass등이 호출되므로 위 순서에 위반된다. 이런 제약이 생기는 이유는 이벤트 기반의 API 를 이용하고 있기 때.. 더보기
[Java] ASM 을 이용한 클래스 멤버 삭제하기 소스 파일 이름, 이너 클래스 와 아우터 클래스의 정보 들은 디버깅을 위한 용도로만 사용되고 삭제 되어도 동작에는 문제가 없다. 삭제하는 것 또한 단순하다. 이벤트가 발생했을 때 ClassVistor 를 상속한 Adaptor에서 ClassWriter로 아무 것도 전달하지 않으면 결과적으로 생성된 클래스에서는 삭제되는 것과 같다. 필드나 메소드의 경우는 조금 더 생각해야 한다. 물론, 전혀 어렵지 않다!visitField 나 visitMethod 메소드의 경우 결과를 반환해야 하는데 이를 null로 반환하는 것이다. 더보기
[Java] ASM을 이용한 클래스 파일 변환 ClassReader 사용 예제와 ClassWriter 사용 예제는 이미 보았으니, 이젠 둘을 함께 사용하는 하는 경우를 보자. 사실, 두 클래스를 함께 사용하는 경우가 일반적으로 쓰이는 경우라 볼 수 있다. 소스 코드의 변경없이 사용하는 모든 클래스에 어떤 변경을 하려고 하는 경우 java.lang.instrument 패키지의 ClassFileTransformer를 사용한다. (참고 : example of java class transform with java agent and BCI) 첫번째로 아무 작업 없이 읽은 그대로 반환하는 코드이다. 위 코드의 내용을 ClassReader 와 ClassWriter를 이용하여 채워보자. 이 코드에서는 ClassReader(event producer) 와 Clas.. 더보기
[Java] ASM을 이용한 클래스 생성 이전 글에서는 ClassReader를 사용한 예를 보았다. 이번에는 ClassWriter를 사용한 예제를 만들어 보자. 우선, ClassWriter의 사용 예제인 만큼 복잡한 클래스는 제쳐두고 필드 몇개와 메소드를 선언하는 인터페이스 클래스를 만들어 본다. 만들어 볼 클래스 위의 클래스를 직접 바이트 코드로 생성하기 위한 클래스 위의 두 경우를 비교해 보면 직접 바이트 코드로 생성하는 것이 훨씬 복잡하다. 따라서, 일반적인 코딩을 위한 목적으로는 사용하지 않고, 동적으로 코드를 생성하거나 기존의 클래스를 변환하는 용도로 사용하는 것이 일반적이다. 이를 위해 ClassLoader를 사용하거나 ClassFileTransformer를 이용하는 방법이 있다. 이는 다음 기회에 알아보기로... 더보기
[Java] ASM을 이용한 .class 파일 파싱 .class 파일의 내용을 javap 로 확인한 것과 비슷하게 보여주기로 하자. 첫번째 할 일은 .class 파일의 내용을 보여주는 ClassVisitor 클래스의 자식 클래스를 만드는 것이다. 간략한 코드는 다음과 같다. 두번째로 ClassPrinter 클래스와 ClassReader 요소를 연결하여 ClassReader 에서 발생하는 이벤트를 사용할 수 있도록 한다. 두번째 줄은 HelloWorld.class를 파싱하는 ClassReader를 만든다. 마지막 줄의 accept 메소드는 HelloWorld.class를 파싱하고 cp 에 구현된 해당 ClassVisitor 메소드를 호출한다. 완성된 ClassView 결과 ASM 에는 Textifier라는 이미 잘 만들어진 툴이 있다. 사용법은 이 글을 참.. 더보기
[Java] javap 프로그램을 이용하여 .class파일 출력 테스트 용 자바 코드 compile> javac HelloWorld.java javap 실행> javap -s -v HelloWorld.class 결과 더보기
[Java]컴파일된 클래스 내부에서의 타입 및 메소드 표현 class or interface typeinternal names점(.)이 슬래쉬(/) 변경된 풀네임String -> java/lang/String Type descriptor Java type Type descriptor boolean Z char C byte B short S int I float F long J double D Object Ljava/lang/Object; int [] [I Object [] [] [[Ljava/lang/Object; 참고 : http://download.forge.objectweb.org/asm/asm4-guide.pdfFigure 2.2.: Type descriptors of some Java types Method descriptor ( + 파라메터 type .. 더보기
[Java]컴파일된 클래스 구조 byte code 로 컴파일 된 클래스의 대략적인 구조는 다음과 같다. public 또는 private 같은 modifiers, 이름, 부모 클래스, 인터페이스, 어노테이션 들로 구성된 하나의 섹션선언된 필드 당 하나의 섹션필드의 modifiers, 이름, type, 어노테이션 들로 구성생성자 와 메소드 당 하나의 섹션메소드의 modifiers, 이름, 반환 및 파라미터 타입, 어노테이션 들로 구성자바 바이트 코드 인스트럭션들이 나열된 형태로 이루어진 컴파일 된 코드 포함 소스 코드와 컴파일 된 코드의 차이점컴파일 된 클래스는 오직 하나의 클래스만으로 구성된다. 반면, 소스코드는 하나 이상의 inner 클래스를 포함 수 있다.예를 들어, 하나의 inner 클래스를 가지는 소스 코드의 경우메인 클래스가 컴.. 더보기