월요일, 4월 28, 2008

개발 추억 되집기

(http://hangumkj.blogspot.com/2005/10/blog-post_18.html)

오늘 다른 일로 위의 날자에 개발한 은행 담당자와 전화 통화를 했습니다.
아직도 같은 팀에 있었으며, 팀원이었으나 팀장이 되어 있었습니다.

그때 개발한 결과물을 잘 사용하고 있냐고 조심 스럽게 물었습니다.




혹여 삽질해서 내가 개발한 프레임웍을 엎어 버렸으면....
혹은 항상 에러에 문제로 고민거리 산출물이면 어떨까 싶어서.. 내심 걱정스럽게...

담당자와 통화 하였고, 그때 내가 개발한 결과물에 더해, 그때 보다 두배가 넘는 보고서를 출력하고 있으며, 유지보수 계약도 안맺고 직접 수정하고 있다 하였습니다.
(사실 동적으로 보고서를 추가삭제하고, 동적으로 모시기 해주는 기능이 많은 아이라, 사용법이 복잡해 내심 걱정했습니다.)
거기다 사용해보니 아주 잘된 프레임웍이라고 아주 고맙다고 아주 잘 쓰고 있다고 합니다.
(물런, 상투적일수도 있겠습니다만)

내심 걱정하고 전화했는데.. '고맙다'는 이야기를 들으니..
ㅎㅎ

라이센스, 제품에 대하여...

개발이 거의 마무리 되어 제품의 '라이센스', '제품에대하여'를 작성해야 합니다.
그러다 이런 이야기에 대해 잼이있게 읽었던 알탱이 알집의 제품에 대하여를 읽고 있습니다.
몇년전에 읽었을때는 그냥 재미있기만 했는데, 지금은 몬가 느껴지는 듯 합니다.
베타버전에 대하여도 그렇고, 무료 라이센스에 대한 이야기도 그렇습니다.

사용자가 원하는 제품을 빌드하는 것은 어렵긴 어려운 모양 입니다.

이런 일을 할때마다 좀더 노력해야지 하지만, 천천히 편안함을 추구하고 싶습니다.
사실 경제적인 부분과 어느정도 나의 시간이 보장된다면 다시한번 힘을 내보고 싶기는 합니다.

살짝만요.

화요일, 4월 22, 2008

bcel을 사용하여 메소드 내용삭제

/**
* 이번 3번째 예제에서는 클래스 메소드 삭제를 해보도록 하겠습니다.
*
* 이번 예제에서는 TestAppendMethodBuild에서 만들었던 TestAppend 클래스의 메소드 private static void
* appendMethod(String str)의 내용을 삭제하는 예제를 만들어 보도록 하겠다.
*
* 3번재 예제에서야 조금 bcel의 면목을 보는듯 하다.
* 사실 위의 예제도 상속을 사용하면 정상적으로 수정가능하겠으나, 지금까지는 예제를 만들고 있으므로 이해해주시기를....
*
* 그럼, 본격적인 예제를 만들어보도록 하자.
*
* 프로그램을 실행하고 난 다음에는 다음과 같은 결과를 예상할 수 있다.
*
* public class TestAppend {
* private static void appendMethod(String str) {
* }
*
* public static void main(String[] args) {
* System.out.println("BCEL Start..."); String str = "..test bcel...";
*
* System.out.println("Str Value " + str);
* appendMethod(str);
* }
* }
*
* 이 예제가 끝나면 TestAppend 예제의 main 메소드를 수정하는 예제를 만들어 보도록 하겠다.



package com.test;

import com.sun.org.apache.bcel.internal.classfile.ClassParser;
import com.sun.org.apache.bcel.internal.classfile.JavaClass;
import com.sun.org.apache.bcel.internal.classfile.Method;
import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen;
import com.sun.org.apache.bcel.internal.generic.Instruction;
import com.sun.org.apache.bcel.internal.generic.InstructionHandle;
import com.sun.org.apache.bcel.internal.generic.InstructionList;
import com.sun.org.apache.bcel.internal.generic.MethodGen;

/**
* 이번 3번째 예제에서는 클래스 메소드 삭제를 해보도록 하겠습니다.
*
* 이번 예제에서는 TestAppendMethodBuild에서 만들었던 TestAppend 클래스의 메소드 private static void
* appendMethod(String str)의 내용을 삭제하는 예제를 만들어 보도록 하겠다.
*
* 3번재 예제에서야 조금 bcel의 면목을 보는듯 하다.
* 사실 위의 예제도 상속을 사용하면 정상적으로 수정가능하겠으나, 지금까지는 예제를 만들고 있으므로 이해해주시기를....
*
* 그럼, 본격적인 예제를 만들어보도록 하자.
*
* 프로그램을 실행하고 난 다음에는 다음과 같은 결과를 예상할 수 있다.
*
public class TestAppend {
* private static void appendMethod(String str) {
* }
*
* public static void main(String[] args) {
* System.out.println("BCEL Start..."); String str = "..test bcel...";
*
* System.out.println("Str Value " + str);
* appendMethod(str);
* }
* }

* 이 예제가 끝나면 TestAppend 예제의 main 메소드를 수정하는 예제를 만들어 보도록 하겠다.
*
* @author hangum
*
*/
public class TestDeleteMethodBuilder {
static String orgClassName = "build/TestAppend.class";

/**
* @param args
*/
public static void main(String[] args) {
// 해당 클래스를 불러온다.
JavaClass classz = null;
try {
classz = new ClassParser(orgClassName).parse();
} catch (Exception e) {
System.out.println(orgClassName + "가 존재 하지 않습니다.");
System.exit(0);
}

Method[] methods = classz.getMethods();
ConstantPoolGen cp = new ConstantPoolGen(classz.getConstantPool());

for (int i = 0; i < methods.length; i++) {
MethodGen mg = new MethodGen(methods[i], classz.getClassName(), cp);

// appendMethod delete
if("appendMethod".equals(methods[i].getName())) {

System.out.println(" ### [작업 method name] " + mg.getName() + " [Signature] " + methods[i].getSignature());

InstructionList il = mg.getInstructionList();
InstructionHandle[] ih = il.getInstructionHandles();

for(int j=0; j < ih.length; j++) {
Instruction inst = ih[j].getInstruction();

try {
if(!"return".equals(inst.getName())) il.delete(inst);
} catch(Exception e) {
System.out.println("==> error rise on [name] " + inst.getName() + " [message] " + e.getMessage());
e.printStackTrace();
}
}

methods[i] = mg.getMethod();
il.dispose();
}
} // end for

/*
* Dump the class to "class name"_.class
*/
String dumpClassName = "c:/temp/" + classz.getClassName() + ".class";
try {
classz.setConstantPool(cp.getFinalConstantPool());
classz.dump(dumpClassName);
} catch (Exception e) {
e.printStackTrace();
}

System.out.println("== 종료했습니다.");
}
}

bcel을 사용하여 메소드 내용삭제

/**
* 이번 3번째 예제에서는 클래스 메소드 삭제를 해보도록 하겠습니다.
*
* 이번 예제에서는 TestAppendMethodBuild에서 만들었던 TestAppend 클래스의 메소드 private static void
* appendMethod(String str)의 내용을 삭제하는 예제를 만들어 보도록 하겠다.
*
* 3번재 예제에서야 조금 bcel의 면목을 보는듯 하다.
* 사실 위의 예제도 상속을 사용하면 정상적으로 수정가능하겠으나, 지금까지는 예제를 만들고 있으므로 이해해주시기를....
*
* 그럼, 본격적인 예제를 만들어보도록 하자.
*
* 프로그램을 실행하고 난 다음에는 다음과 같은 결과를 예상할 수 있다.
*
* public class TestAppend {
* private static void appendMethod(String str) {
* }
*
* public static void main(String[] args) {
* System.out.println("BCEL Start..."); String str = "..test bcel...";
*
* System.out.println("Str Value " + str);
* appendMethod(str);
* }
* }
*
* 이 예제가 끝나면 TestAppend 예제의 main 메소드를 수정하는 예제를 만들어 보도록 하겠다.



package com.test;

import com.sun.org.apache.bcel.internal.classfile.ClassParser;
import com.sun.org.apache.bcel.internal.classfile.JavaClass;
import com.sun.org.apache.bcel.internal.classfile.Method;
import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen;
import com.sun.org.apache.bcel.internal.generic.Instruction;
import com.sun.org.apache.bcel.internal.generic.InstructionHandle;
import com.sun.org.apache.bcel.internal.generic.InstructionList;
import com.sun.org.apache.bcel.internal.generic.MethodGen;

/**
* 이번 3번째 예제에서는 클래스 메소드 삭제를 해보도록 하겠습니다.
*
* 이번 예제에서는 TestAppendMethodBuild에서 만들었던 TestAppend 클래스의 메소드 private static void
* appendMethod(String str)의 내용을 삭제하는 예제를 만들어 보도록 하겠다.
*
* 3번재 예제에서야 조금 bcel의 면목을 보는듯 하다.
* 사실 위의 예제도 상속을 사용하면 정상적으로 수정가능하겠으나, 지금까지는 예제를 만들고 있으므로 이해해주시기를....
*
* 그럼, 본격적인 예제를 만들어보도록 하자.
*
* 프로그램을 실행하고 난 다음에는 다음과 같은 결과를 예상할 수 있다.
*
* public class TestAppend {
* private static void appendMethod(String str) {
* }
*
* public static void main(String[] args) {
* System.out.println("BCEL Start..."); String str = "..test bcel...";
*
* System.out.println("Str Value " + str);
* appendMethod(str);
* }
* }
*
* 이 예제가 끝나면 TestAppend 예제의 main 메소드를 수정하는 예제를 만들어 보도록 하겠다.
*
* @author hangum
*
*/
public class TestDeleteMethodBuilder {
static String orgClassName = "build/TestAppend.class";

/**
* @param args
*/
public static void main(String[] args) {
// 해당 클래스를 불러온다.
JavaClass classz = null;
try {
classz = new ClassParser(orgClassName).parse();
} catch (Exception e) {
System.out.println(orgClassName + "가 존재 하지 않습니다.");
System.exit(0);
}

Method[] methods = classz.getMethods();
ConstantPoolGen cp = new ConstantPoolGen(classz.getConstantPool());

for (int i = 0; i < methods.length; i++) {
MethodGen mg = new MethodGen(methods[i], classz.getClassName(), cp);

// appendMethod delete
if("appendMethod".equals(methods[i].getName())) {

System.out.println(" ### [작업 method name] " + mg.getName() + " [Signature] " + methods[i].getSignature());

InstructionList il = mg.getInstructionList();
InstructionHandle[] ih = il.getInstructionHandles();

for(int j=0; j < ih.length; j++) {
Instruction inst = ih[j].getInstruction();

try {
if(!"return".equals(inst.getName())) il.delete(inst);
} catch(Exception e) {
System.out.println("==> error rise on [name] " + inst.getName() + " [message] " + e.getMessage());
e.printStackTrace();
}
}

methods[i] = mg.getMethod();
il.dispose();
}
} // end for

/*
* Dump the class to "class name"_.class
*/
String dumpClassName = "c:/temp/" + classz.getClassName() + ".class";
try {
classz.setConstantPool(cp.getFinalConstantPool());
classz.dump(dumpClassName);
} catch (Exception e) {
e.printStackTrace();
}

System.out.println("== 종료했습니다.");
}
}

일요일, 4월 20, 2008

bcel 셈플을 만들어서 블로그에 공개하고 있는데, 흠 사실 예제야 모 어찌 저찌 해서 고생하면 다 만들수 있는 문제일수도 있다.

사실은 bcel을 사용하여 jvm의 기본 원리 및 구조를 파악하는 것이 먼저 이겠으나, 흠냐리 봐야할거 좀 많다. jvm spec을 어느정도는 알고 있어야 가능하겠다.

SUN 공식 JVM SPEC 책
http://java.sun.com/docs/books/jvms/second_edition/html/VMSpecTOC.doc.html

JVM SPEC 책
http://www.artima.com/insidejvm/ed2/jvm.html

BCEL 홈
http://jakarta.apache.org/bcel/manual.html

ASM 홈
http://asm.objectweb.org/

BCEL을 어느정도 보신 분이라면 알겠지만, 자료가 너무 부족하다. 나는 약간 미완성인듯한 느낌까지 받았다.

ASM 경우는 ECLIPSE PLUG-IN이 있는데, 이것도 많이 유용하다 하겠습니다.
이름은 Bytecode Outline이고 http://andrei.gmxhome.de/bytecode/index.html입니다.

이런거 저런거 귀찮다면 자바에디터로 eclipse를 사용하실텐데 f3를 눌러보시면 된다.
물런 이런 코드를 처음에는 보기 어렵겠지만, 위의 문서를 어느정도 본다면 눈에 차차 들어 올테니.. 도움이 될것이다.

셈플 만드는 작업이 끝나면 어떤 모양으로든 다른 분들에게 도움이 되는 것을 만들어보도록 하겠습니다.
좋은 아이디어 있는 분 말씀해주세요

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("== 작업을 끝냈습니다.");
}
}

수요일, 4월 16, 2008

그동안 말만 하고 미뤄두었던 일들을 해나가겟다.

1) 우선 영어 한절씩 외우기
2) becl 셈플 및 작은 강좌를 시작
3) Vocabulary plug-in도 업그레이드 시작
4) Logviewer rcp도 새롭게 시작

하도록 하겠다.

실행으로 옮겨지고 피가 되고 살이되기를 작게 나마 소망해본다

일요일, 4월 06, 2008

아주 가끔 삶에 대해 감사하고 희열을 느낄때가 있습니다.
전혀 예상하지 않았던 곳에서의 환대 혹은 나에대한 지지는 내가 살고있는것에 대한 감사와 힘이 되는듯 합니다.

사실 내가 한 일이 전혀 없는대도, 그냥 퍼 주시는 분들을 볼때마다.. 기쁨인데요.

나도 누군가에게 이런 기쁨을 전하고 싶습니다.

이번주 그런 이벤트가 두건 아니 세건 있었습니다.
몇달동안 있어야할 이벤트가 연속이라니.. 2008년 한해동안은 어떡하죠?
내 행운을 돌려주시길...