일요일, 4월 20, 2008

bcel 두번째 sample

미력하나마 두번째 예제 소스 입니다.

처음 예제는 bcel을 사용하여 기본 Test코드를 생성 하였다면 두번째 예제는
그 예제에 간단한 메소드 하나를 추가하는 것으로 예제를 만들어 보도록 하겠습니다.
아래 보시면 알겠지만 appendMethod(str)을 추가한것이고 private static 으로 시작하는 메소드가 추가 되어 있습니다.

참고로 sun jdk 1.6을 사용했고, apache에 있는 bcel 5.2와 같은 것으로 생각됩니다

* public class TestAppend {
* public static void main(String[] args) {
* System.out.println("BCEL Start...");
*
* String str = "..test bcel..."; *
* System.out.println("Str Value " + str);
*
* appendMethod(str);
* }
*
* private static void appendMethod(String str) {
* System.out.println("appendMethod value is " + str);
* }
* }


bcel로 다음과 같은 소스를 만들어 보겠습니다.

package com.test;

import java.io.IOException;

import org.apache.bcel.verifier.structurals.LocalVariables;

import com.sun.org.apache.bcel.internal.Constants;
import com.sun.org.apache.bcel.internal.generic.ALOAD;
import com.sun.org.apache.bcel.internal.generic.ASTORE;
import com.sun.org.apache.bcel.internal.generic.ArrayType;
import com.sun.org.apache.bcel.internal.generic.ClassGen;
import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen;
import com.sun.org.apache.bcel.internal.generic.INVOKESTATIC;
import com.sun.org.apache.bcel.internal.generic.InstructionConstants;
import com.sun.org.apache.bcel.internal.generic.InstructionFactory;
import com.sun.org.apache.bcel.internal.generic.InstructionList;
import com.sun.org.apache.bcel.internal.generic.LocalVariableGen;
import com.sun.org.apache.bcel.internal.generic.MethodGen;
import com.sun.org.apache.bcel.internal.generic.ObjectType;
import com.sun.org.apache.bcel.internal.generic.PUSH;
import com.sun.org.apache.bcel.internal.generic.Type;

/**
* jdk 1.6에 있는 것으로..
*
* 이번 것은 메소드를 추가한다.
*
* public class Test {
* public static void main(String[] args) {
* System.out.println("BCEL Start...");
*
* String str = "..test bcel..."; *
* System.out.println("Str Value " + str);
*
* appendMethod(str);
* }
*
* private static void appendMethod(String str) {
* System.out.println("appendMethod value is " + str);
* }
* }
*
* @author hangum
*
*/
public class TestAppendMethodBuilder {
/**
* method를 추가한다
*
* @param cg ClassGen
* @param msg mag index
*/
public static void appendMethod(ClassGen cg) {
InstructionList il = new InstructionList();

MethodGen mg = new MethodGen(
Constants.ACC_STATIC | Constants.ACC_PRIVATE,
Type.VOID,
new Type[]{ Type.STRING },
new String[]{ "str" },
"appendMethod",
"TestAppend",
il,
cg.getConstantPool()
);

InstructionFactory factory = new InstructionFactory(cg);

il.append(
factory.createFieldAccess(
"java.lang.System",
"out",
new ObjectType("java.io.PrintStream"),
Constants.GETSTATIC)
);

// variable setting
LocalVariableGen[] arLvg = mg.getLocalVariables();
il.append(new ALOAD(arLvg[0].getIndex()));

il.append(factory.createInvoke("java.io.PrintStream", "println",
Type.VOID, new Type[] { Type.STRING },
Constants.INVOKEVIRTUAL));

il.append(InstructionConstants.RETURN);

mg.setMaxStack();
cg.addMethod(mg.getMethod());
}

/**
*
* @param args
*/
public static void main(String[] args) {
System.out.println("== 작업을 시작했습니다. ");

ClassGen cg = new ClassGen("TestAppend", // class name
"java.lang.Object", // super class
"",
Constants.ACC_PUBLIC | Constants.ACC_SUPER,
null);

ConstantPoolGen cp = cg.getConstantPool();
InstructionList il = new InstructionList();

// method 생성
MethodGen mg = new MethodGen(
Constants.ACC_STATIC | Constants.ACC_PUBLIC,
Type.VOID,
new Type[] {
new ArrayType(Type.STRING, 1)
},
new String[] { "args" },
"main",
"TestAppend",
il,
cp);

InstructionFactory factory = new InstructionFactory(cg);

ObjectType p_stream = new ObjectType("java.io.PrintStream");

il.append(factory.createFieldAccess("java.lang.System", "out",
p_stream, Constants.GETSTATIC));
il.append(new PUSH(cp, "BCEL Start..."));
il.append(factory.createInvoke("java.io.PrintStream", "println",
Type.VOID, new Type[] { Type.STRING },
Constants.INVOKEVIRTUAL));

// 변수 str 생성
LocalVariableGen lvgStr = mg.addLocalVariable("str", Type.STRING, null,
null);
int str = lvgStr.getIndex();
il.append(new PUSH(cp, "..test bcel..."));
lvgStr.setStart(il.append(new ASTORE(str)));

// str Value + str
il.append(factory.createFieldAccess("java.lang.System", "out",
p_stream, Constants.GETSTATIC));
il.append(factory.createNew(Type.STRINGBUFFER));
il.append(InstructionConstants.DUP);
il.append(new PUSH(cp, "Str Value, "));
il.append(factory.createInvoke("java.lang.StringBuffer",
"", Type.VOID, new Type[] { Type.STRING },
Constants.INVOKESPECIAL));
il.append(new ALOAD(str));
il.append(factory.createInvoke("java.lang.StringBuffer", "append",
Type.STRINGBUFFER, new Type[] { Type.STRING },
Constants.INVOKEVIRTUAL));
il.append(factory.createInvoke("java.lang.StringBuffer", "toString",
Type.STRING, Type.NO_ARGS, Constants.INVOKEVIRTUAL));

il.append(factory.createInvoke("java.io.PrintStream", "println",
Type.VOID, new Type[] { Type.STRING },
Constants.INVOKEVIRTUAL));

// method 추가하고 호출하는 코드를 삽입한다
appendMethod(cg);

il.append(new ALOAD(str));
int appendMethod = cp.addMethodref("TestAppend", "appendMethod", "(Ljava/lang/String;)V");
il.append(new INVOKESTATIC(appendMethod));

// return void
il.append(InstructionConstants.RETURN);

mg.setMaxStack();
cg.addMethod(mg.getMethod());

il.dispose();

// construct
cg.addEmptyConstructor(Constants.ACC_PUBLIC);

// 파일생성
try {
cg.getJavaClass().dump("build/TestAppend.class");
} catch (IOException ioe) {
ioe.printStackTrace();
}

System.out.println("== 작업을 끝냈습니다.");
}
}

댓글 없음:

댓글 쓰기