레이블이 ASM인 게시물을 표시합니다. 모든 게시물 표시
레이블이 ASM인 게시물을 표시합니다. 모든 게시물 표시

2014년 2월 13일 목요일

ASM 4.0 Example - Hello World 주석 달기

import java.io.FileOutputStream;
import java.io.PrintStream;

import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.GeneratorAdapter;
import org.objectweb.asm.commons.Method;

/**
 * @author Eric Bruneton
 */
public class Helloworld extends ClassLoader implements Opcodes {

public static void main(final String args[]) throws Exception {

        // 아래의 소스에 대하여 자바 클래스 파일에 해당하는 바이트 코드를 만들기
        /**********************************************************************
        public class Example {
            public static void main (String[] args) {
                System.out.println("Hello world!");
            }
        }
        **********************************************************************/

// ClassWriter 만들기 - Object 를 상속 받아서
ClassWriter cw = new ClassWriter(0);
        // visit(int version, int access, String name, String signature, String superName, String[] interfaces)
cw.visit(V1_1, ACC_PUBLIC, "Example", null, "java/lang/Object", null);

// 생성자 MethodWriter 만들기
        // visitMethod(int access, String name, String desc, String signature, String[] exceptions)
MethodVisitor mw = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);

        // visitVarInsn(int opcode, int var)
        // opcode 는 ILOAD, LLOAD, FLOAD, DLOAD, ALOAD, ISTORE, LSTORE, FSTORE, DSTORE, ASTORE, RET 중 선택사용
        // opcode 참조 : http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-6.html
        // 'this' 변수 지정
mw.visitVarInsn(ALOAD, 0);

// super class constructor
        // visitMethodInsn(int opcode, String owner, String name, String desc)
        // opcode 는 INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC, INVOKEINTERFACE 중 선택사용
mw.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V");

        // visitInsn(int opcode)
mw.visitInsn(RETURN);

        // visitMaxs(int maxStack, int maxLocals)
        // 메소드의 최대 스택 사이즈
        // 메소드를 위한 로컬 변수의 최대 사이즈
mw.visitMaxs(1, 1);

mw.visitEnd();

// main 함수 만들기
        // visitMethod(int access, String name, String desc, String signature, String[] exceptions)
mw = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "main", "([Ljava/lang/String;)V", null, null);

// System 클래스의 'out' field 사용
        // visitFieldInsn(int opcode, String owner, String name, String desc)
        // opcode 는 GETSTATIC, PUTSTATIC, GETFIELD, PUTFIELD 중 선택사용
mw.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");

// "Hello World!" String 상수 사용 (ldc instruction)
        // ldc pushes a one-word constant onto the operand stack. int, float, String 등
  mw.visitLdcInsn("Hello world!");
        
// 'prinln' 수행
mw.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V");

        mw.visitInsn(RETURN);

        // visitMaxs(int maxStack, int maxLocals)
        // 메소드의 최대 스택 사이즈
        // 메소드를 위한 로컬 변수의 최대 사이즈
mw.visitMaxs(2, 2);

mw.visitEnd();

// 바이트코드 값 얻기
byte[] code = cw.toByteArray();

// class 파일 만들기
        FileOutputStream fos = new FileOutputStream("Example.class");
fos.write(code);
fos.close();

// 클래스로더로 읽어 들이기
        Helloworld loader = new Helloworld();
Class<?> exampleClass = loader.defineClass("Example", code, 0, code.length);

// 로딩된 클래스의 main 메소드 수행하기
exampleClass.getMethods()[0].invoke(null, new Object[]{null});

// ------------------------------------------------------------------------
// GeneratorAdapter를 이용하여 만들기 (편리하지만 느리다 ㅡ.ㅡ;;)
// ------------------------------------------------------------------------
        
cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
cw.visit(V1_1, ACC_PUBLIC, "Example", null, "java/lang/Object", null);

        // 생성자 만들기
Method m = Method.getMethod("void <init> ()");
        // GeneratorAdapter(int access, Method method, String signature, Type[] exceptions, ClassVisitor cv)
GeneratorAdapter mg = new GeneratorAdapter(ACC_PUBLIC, m, null, null, cw);
mg.loadThis();
mg.invokeConstructor(Type.getType(Object.class), m);
mg.returnValue();
mg.endMethod();

// main 함수 만들기
m = Method.getMethod("void main (String[])");
        // GeneratorAdapter(int access, Method method, String signature, Type[] exceptions, ClassVisitor cv)
mg = new GeneratorAdapter(ACC_PUBLIC + ACC_STATIC, m, null, null, cw);
mg.getStatic(Type.getType(System.class), "out", Type.getType(PrintStream.class));
mg.push("Hello world!");
mg.invokeVirtual(Type.getType(PrintStream.class), Method.getMethod("void println (String)"));
mg.returnValue();
mg.endMethod();

cw.visitEnd();

        // 바이트코드 값 얻기
code = cw.toByteArray();

        // 클래스로더로 읽어 들이기
loader = new Helloworld();
exampleClass = loader.defineClass("Example", code, 0, code.length);

        // 로딩된 클래스의 main 메소드 수행하기
exampleClass.getMethods()[0].invoke(null, new Object[]{null});
}
}


2014년 2월 7일 금요일

ASM 4.0 Guide - 1 Days

1. introduction

1.1 Movivations

ASM 은 자바 바이트코드 엔지니어링 라이브러리(a java bytecode engineering library)으로 다음의 이점이 있다.


  • Program analysis : 파싱에서 부터 애플리케이션의 잠재적인 버그를 찾거나, 사용하지 않는 코드, 역공학에 사용
  • Program generation : 일반 컴파일러나 Just in Time 컴파일러 같이 분산 프로그래밍에서 사용할 스텁, 스켈레톤 컴파일러가 사용할 프로그램을 작성
  • Program transformation : 프로그램을 최적화 하거나 AOP같이 성능 모니터링 이나 디버깅용 코드를 추가
그것도 runtime 시에 가능하다.

1.2 Overview

1.2.1 Model

ASM 라이브러리는 2개의 API 를 제공한다.

  • core API : event based model
- 연속적인 이벤트로 클래스를 표현한다.
- 각 이벤트는 클래스의 특정 구성 요소를 나타낸다.
- 이벤트 기반 API는 사용 가능한 이벤트, 반드시 따라야 하는 순서, 파싱할 엘리먼트 당 하나의 이벤트를 생성하는 클래스 파서, 연속적인 이벤트에서 컴파일된 클래스를 생성하는 클래스 작성기를 제공한다.
  • tree API : object based model
- 객체 트리로 클래스를 표현한다.
- 각 객체가 클래스 구성 요소를 나타낸다.
- 각 객체는 자신의 하위 구성 요소에 대한 객체들을 나타내는 레퍼런스를 가지고 있다.
- 객체 기반 API는 연속적인 이벤트 모델을 객체 트리 모델로 변경하는 하거나 그 반대로 변경하는 기능을 제공한다.
- 객체 기반 API는 이벤트 기반 API를 근간으로 만들어졌다.

이벤트 기반 API가 더 좋다.

- 객체 기반 API 보다 빠르고 메모리 소비가 적다.
- 클래스 변형이 객체 기반 모델 보다 어렵다. 한번에 한 엘리먼트만 조작하니까.


1.2.2 Organization


  • asm.jar
org.objectweb.asm, org.objectweb.asm.signature
event based API
클래스 파서, 클래서 생성기(class writer) 등의 컴포넌트

  • asm-util.jar 
org.objectweb.asm.util

  • asm-common.jar
 org.objectweb.asm.commons
미리 정의해 둔 클래스 트랜스포머

  • asm-tree.jar 
 org.objectweb.asm.tree
object based API

  • asm-analysis.jar 
tree API 기반의 클래스 분석 프레임워크와 미리 만들어 둔 클래스 분석기 제공