모 이런 거 어딘가 있다는 얘길 들었는데, 내가 만들면 더 잘 할 수 있을 거 같아서 한번 만들어 봤다.
하다가 귀찮아져서 겨우 문제 없이 돌아가는 수준에서 멈췄으니 고쳐 쓸 사람은 얼마든지 고쳐서 쓰시길...

용도는 아무래도 바이트 단위의 길이로 정의된 DB 컬럼에 데이타를 넣을 때,
어쩔 수 없이 잘라서 넣어야 하는 경우가 생기는데 이럴 때 이 메소드 한방으로 해결.
바이트 단위라는 부분에서 냄새를 맡았겠지만, 한글을 비롯한 한글자가 2바이트 이상을 사용할 때에 유용하겠다.
오라클 같은 경우 VARCHAR2 길이가 4000바이트 밖에 안 되다 보니 긴 내용을 넣기에 좀 부족한 느낌이 있는데,
그렇다고 LONG이나 CLOB를 쓰는 건 성능도 안 좋고, 다루기도 불편하니
이런 식으로 잘라서 VARCHAR2 컬럼에 넣는 방법을 종종 사용한다고 한다.

첫번째 메소드는 원하는 바이트수만큼만으로 이루어진 String 리턴
getMaxByteString(str, 400) 을 호출하면 str이라는 문자열에서 앞에서 최대 400바이트만큼 잘라서 문자열으로 만들어 리턴
즉, 리턴한 문자열을 보면 str이 400바이트 이상이면 399바이트 아니면 400바이트이겠고, 그보다 짧으면 통째로 리턴할 것이다.
[code java] // str이라는 문자열의 맨앞부터 최대 maxLen만큼의 바이트수로 이루어진 문자열을 잘라서 리턴 public static StringgetMaxByteString(String str, int maxLen) { StringBuilder sb = new StringBuilder(); int curLen = 0; String curChar; for (int i = 0; i < str.length(); i++) { curChar = str.substring(i, i+1); curLen += curChar.getBytes().length; if (curLen > maxLen) break; else sb.append(curChar); } return sb.toString(); } [/code]
두번 째 메소드는 원하는 바이트수(maxLen)만큼만으로 이루어진 String 배열을 str 문자열 끝까지 처리해서 리턴
getMaxByteStringArray(str, 400) 을 호출하면 str이라는 문자열에서 앞에서 최대 400바이트만큼 잘라서 문자열로 만들고
그 후에 문자열이 또 있으면 또 이어서 최대 400바이트만큼 잘라서 문자열을 만들고. 이걸 문자열 끝까지...
만들어진 문자열을 배열로 만들어서 리턴
별도 테이블을 만들어서 각 문자열을 하나의 로우에 저장하도록 구성한다면 이것도 괜찮을 듯.
[code java] // str이라는 문자열의 맨앞부터 끝까지 최대 maxLen만큼의 바이트수로 이루어진 문자열을 // 연속으로 잘라서 String 배열로 리턴 public static String[]getMaxByteStringArray(String str, int maxLen) { return getMaxByteStringArray(str, maxLen, -1); } [/code]
세번째 메소드는 원하는 바이트수(maxLen)만큼만으로 이루어진 String 배열을 최대 maxArrays만큼 길이로 리턴
getMaxByteStringArray(str, 400, 3) 을 호출하면 str이라는 문자열에서 앞에서 최대 400바이트만큼 잘라서 문자열로 만들고
그 후에 문자열이 또 있으면 또 이어서 최대 400바이트만큼 잘라서 문자열을 만들고. 이걸 문자열을 최대 3번까지...
만들어진 문자열을 배열로 만들어서 리턴
한 테이블의 3개의 컬럼에 문자열을 쪼개서 저장한다면 유용할 듯.
[code java] // str이라는 문자열의 맨앞부터 최대 maxLen만큼의 바이트수로 이루어진 문자열을 // 연속으로 잘라서 최대 maxArrays 길이의 배열로 리턴 public static String[]getMaxByteStringArray(String str, int maxLen, int maxArrays) { StringBuilder sb = new StringBuilder(); ArrayList strList = new ArrayList(); int curLen = 0; String curChar; for (int i = 0; i < str.length(); i++) { curChar = str.substring(i, i+1); curLen += curChar.getBytes().length; if (curLen > maxLen) { if (maxArrays == -1 || strList.size() <= maxArrays-2) { strList.add(sb.toString()); sb = new StringBuilder(); curLen = 0; i--; } else break; } else sb.append(curChar); } strList.add(sb.toString()); String[] strArr = new String[strList.size()]; for (int i = 0; i < strList.size(); i++) { strArr[i] = strList.get(i); } return strArr; } [/code]
아래는 위의 메소드를 호출하는 샘플 코드
이 코드 돌려 보고 싶으면, 위의 메소드들과 아래의 main 메소드 합쳐서 한 클래스에 넣고 돌리면 된다.
[code java] public static void main(String[] args) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < 1000; i++) { sb.append("codePointAt을 사용하면 문자의 유니코드값을 구할 수 있잖아요.. 근데.. 문자의 유니코드값을 다시 문자로 변환해"); } Stringstr = sb.toString(); String newStr = getMaxByteString(str, 4000); System.out.println(newStr + ":" + newStr.getBytes().length); System.out.println("-----------------------------------------"); String[] strArr = getMaxByteStringArray(str, 4000); for (int i = 0; i < strArr.length; i++) { System.out.println(strArr[i] + ":" + strArr[i].getBytes().length); } System.out.println("-----------------------------------------"); String[] strArr2 = getMaxByteStringArray(str, 4000, 3); for (int i = 0; i < strArr2.length; i++) { System.out.println(strArr2[i] + ":" + strArr2[i].getBytes().length); } } [/code]
한 글자씩 잘라 붙이기라서 오래 걸릴 줄 알았는데, 꽤 긴 문자열도 0.1초 이내에 잘라 내니 쓸 만하군...

'Java_Web' 카테고리의 다른 글

오라클에서 SYSDATE를 이용한 시간 연산  (0) 2009.02.12
Derby 사용하기  (2) 2008.09.29
ASM - 자바 바이트코드 분석하기  (1) 2008.03.07
클래스 위치 찾아 주는 프로그램  (0) 2007.08.15
놀라운 발견  (0) 2007.08.12
AND

전부터 자바소스코드를 읽어들여 분석할 수 있는 방법이 없을까 하는 생각을 많이 했었다.

그러려면 거의 자바 컴파일러 수준이 되어야 할 것 같아서 엄두를 못 내다가 얼마전에 자바 바이트코드를 다룰 수 있는 라이브러리가 있다는 사실을 알게 되었다. 대표적인 것이 아파치의 BCEL과 지금 살펴 보려고 하는 ASM이다.

근데 이런 게 있다는 걸 알긴 했는데 도무지 사람들이 관심이 없어서인지 쓸만한 참고자료 찾기가 너무 힘들었다.

결국 ASM 사이트에서 이것저것 파일을 다운받아서 보다보니 내가 딱 원하는 기능의 예제까지 찾아낼 수가 있었다.

 

일단, BCEL(Byte Code Engineering Library)과 ASM은 자바소스파일을 컴파일해서 얻은 클래스파일(바이트코드)을 읽어 들여 변경하거나 분석하는 데 사용하는 라이브러리다. 자바소스파일 같은 경우는 코드상에 문제가 있을 수 있으니까 이걸 분석하는 건 문제가 있을 가능성이 있지만, 클래스파일은 자바소스코드상에 오류가 없어야 컴파일을 통해 만들 수 있는 것이므로 클래스파일을 분석하는 것이 보다 신뢰성 있는 분석결과를 얻을 수 있지 않겠는가? (나는 아직 클래스파일을 동적으로 변경하거나 이런 건 별로 관심이 없다 보니...)

여기저기 자료를 찾다 보니 BCEL보다 ASM이 속도가 빠르다고 해서 나는 ASM을 써 보기로 결정했다.

 

1. 라이브러리 준비

http://asm.objectweb.org/download/index.html에 가서 ASM 관련 파일을 다운받는다.

여기서는 asm관련 모든 패키지가 들어 있는 asm-all-3.1.jar를 사용하는데, 그러려면 asm-3.1-bin.zip을 다운받아서 압축을 풀면 그 안의 lib/all에 이 파일이 있다.

이 파일 외에도 다른 가이드나 예제 같은 것이 많으니 필요에 따라 함께 다운받으면 된다.

 

2. 분석프로그램 생성

※ 이 클래스가 컴파일되려면 컴파일할 때 클래스패스에 1에서 받은 asm-all-3.1.jar를 등록시켜야 한다.


import java.util.List; 
import org.objectweb.asm.ClassReader; 
import org.objectweb.asm.Opcodes; 
import org.objectweb.asm.tree.ClassNode; 
import org.objectweb.asm.tree.MethodNode; 

public class ClassInfo implements Opcodes { 
public static void main(final String[] args) throws Exception { 
ClassReader cr = new ClassReader("test.Test"); 
ClassNode cn = new ClassNode(); 
cr.accept(cn, ClassReader.SKIP_CODE); 

System.out.println("Class Name : " + cn.name + "\n"); 
System.out.println("Super Class : " + cn.superName + "\n"); 

System.out.println("Interfaces :"); 
List interfaces = cn.interfaces; 
for (int i = 0; i < interfaces.size(); i++) { 
System.out.println(interfaces.get(i)); 

System.out.println("\nMethods :"); 
List methods = cn.methods; 
for (int i = 0; i < methods.size(); ++i) { 
MethodNode method = (MethodNode) methods.get(i); 
System.out.println(method.name + method.desc); 
}

ClassInfo.java

 

코드설명 :

9: 분석하려는 클래스의 패캐지를 포함한 full-name을 인자로 ClassReader 객체를 생성한다.

    여기서 읽기 위해서는 분석하려는 클래스가 클래스패스 경로 안에 반드시 있어야 한다.

12: 아마 클래스파일을 파싱하는 작업이 아닐까 생각이 된다.(아직 잘 몰라서 그만...)

14: 클래스 이름 출력

16: 클래스가 상속한 클래스 출력

18~22: 클래스가 구현한 인터페이스 리스트 출력

24~29: 클래스 내의 메소드 정보 출력

 

3. 분석 대상 클래스를 생성 및 컴파일

위의 ClassInfo 클래스가 test.Test라는 클래스를 분석하려고 하는데 그러려면 아래와 같이 미리 Test를 만들어서 컴파일해서 클래스파일이 위의 클래스가 실행하는 클래스패스 안에 들어가 있어야 한다.

package test; 

import java.io.Serializable; 
import java.util.HashMap; 

public class Test extends HashMap implements Serializable { 

public static String str; 

static { 

str = "abced"; 

public Test() { 

super(); 

 }


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

String str = "abc.dfd.efef.fjskdl"; 

System.out.println(str.replace(".", "/")); 

Test test = new Test(); 

String msg = "message to be printed"; 

int count = 5; 

double d = 1.3; 

float f = 1.3f; 

long l = 170343702; 

HashMap map = new HashMap(); 

test.printMsg(msg, count, d, f, l, map); 

}


public void printMsg(String msg, int count, double d, float f, long l, HashMap map) { 

for (int i = 0; i < count; i++) System.out.println(msg); 

}


public String getString(int i, String str) { 

return "abc"; 

}

}

Test.java

 

4. 분석 실행 및 결과 확인

 

이렇게 한 다음 ClassInfo 클래스를 실행하면 아래와 같은 결과가 나온다.


Class Name : test/Test 
Super Class : java/util/HashMap 
Interfaces : 
java/io/Serializable 
Methods : 
<clinit>()V 
<init>()V 
main([Ljava/lang/String;)V 
printMsg(Ljava/lang/String;IDFJLjav 
getString(ILjava/lang/String;)Ljava


클래스나 수퍼클래스, 인터페이스는 무슨 내용인지 바로 알겠는데, 메소드 부분은 바로 안 들어온다.

짧은 지식으로 대강 설명을 드리자면,

9: <clinit>는 클래스의 static 블럭. ()는 인자가 없음. V는 void로 리턴타입이 없다는 뜻

10: <init>는 constructor. 나머지는 위와 동일

11: main은 main 메소드.[Ljava/lang/String;에서 [로 시작하니까 배열이고, L로 시작하니까 자바클래스일 것 같고, V니까 void

      다 합치면 void main(String[]) 이런 형태가 되려나?

12: 인자에서 L로 시작하는 String과 HashMap은 감이 오는데, IDFJ는 뭔가?

        Test.java 소스를 보면서 맞추면 I는 int, D는 double, F는 float, J는 long가 될 것 같네.

       primitive type은 바이트코드에서 한글자로 줄여서 표현하는 모양이다.

13: 맨 마지막이 V가 아니고 Ljava/lang/String; 이니까 String을 리턴하는 메소드로군...

 

 

이렇게 해서 간단하게 클래스파일에서 간단한 정보를 뽑아 보는 방법을 알아 보았다.

여기서 Test.java를 클래스패스에 연결이 영 안 되는 분은 ClassInfo.java의 8라인에 "test.Test" 대신 "java.lang.String"을 입력해서 실행해 보면 String 클래스의 정보가 쭉 나오는 것을 확인할 수 있다.

 

클래스파일을 이용한 분석의 좋은 점은 JSP 파일을 분석할 수도 있다는 것이다.

JSP를 실행하려면 웹컨테이너가 java파일로 변환하고, 이걸 다시 클래스파일로 컴파일해서 실행하는데 JSP를 실행하고 나면 웹컨테이너 디렉토리 어딘가에 클래스파일이 남아 있다. 그러니까 이 경로만 찾아서 적당히 클래스패스로 잡아 주면 JSP도 분석이 가능한 것이다.

참고로 톰캣의 경우는 {Tomcat_Root}/work/Catalina/localhost 디렉토리 아래에 생기니 클래스패스 잘 잡아서 테스트해 보는 것도 재미있을 수 있겠다.

 

사실, 이 정도 정보 외에도 메소드 내의 각 코드 라인별로도 분석이 가능하다.

그런데 이 정도까지 가게 되면 거의 어셈블리 언어 수준까지 읽을 수 있는 능력이 필요하다.

(ASM이 무엇의 약자인지 아무리 해도 못 찾겠는데, 내 생각에는 ASM이 어셈블리의 약자가 아닌가 하는 생각도 든다.)

나도 학교 다닐 때 보던 기억을 더듬어 어느정도 읽어내긴 했지만 그런 걸 모르는 사람은 거의 암호 수준일 것 같다.

모 어려운 것도 있고, 호기심이 발동한 분들이 열심히 공부하길 바라는 마음도 있고, 이걸 보면서 머리 속에 굉장한 아이디어가 떠오른 것도 있고 해서 더 이상 심화된 내용은 다루지 않아야겠다.

 

궁금하면 공부합시다!


AND

 


WAS에 jar 파일과 class 파일들을 만들어 올려서 사용하다 보면, 서버에서 에러가 나면서 어떤 클래스 파일에 문제가 있다고 메시지가 뜨는 경우가 많다.

그런데 이 클래스가 도무지 어디에 박혀 있는지 찾기가 쉽지 않다.

그냥 클래스파일이면 경로를 뒤지다 보면 나올 수도 있지만 jar 파일 안에라도 들어가 있으면 하나씩 열어 가면서 확인해야 한다.

그래서, jar 파일과 class 파일이 있는 디렉토리만 입력해 주면 포함된 모든 클래스 파일을 뒤져서 해당 클래스 파일을 찾아 주는 프로그램을 만들어 보았다.

본 S/W Architect 카테고리의 이전 포스트 중 '클래스 중복 확인 프로그램'과 기본 로직은 비슷하고 단지 이것은 그냥 필요한 것만 찾아 줄 뿐이다.

대신, 해당 클래스 파일을 모두 찾아 주기 때문에 같은 경로의 클래스 파일이 결과에 여러번 반복되어 나타난다면 중복되어 올라갔다고 볼 수 있으며 이런 것은 되도록 하나만 남도록 하는 것이 찾기 어려운 에러가 발생하는 것을 방지하는 좋은 방법이다.


사용법 :

1. 첨부된 zip 파일의 압축을 푼다.

2. lib.properties에 WAS 동작시 로딩되는 jar 파일 디렉토리(lib)와 class 파일 디렉토리(classes)를 모두 입력한다.

   jar를 포함한 디렉토리는 jar로 시작해서 일련번호를 붙이고, class파일을 포함한 디렉토리는 class로 시작해서 일련번호를 붙인다.

   단, 경로는 절대경로로 입력하며 경로구분자는 반드시 "/"로 해야 한다. "\"일 경우는 바꿔 주어야 한다.(이건 귀차니즘 때문에.. ^^;)

   웹애플리케이션을 개발할 경우, 보통 jar를 포함하는 lib 디렉토리들은 WAS 루트의 lib, server/lib, 웹애플리케이션의 WEB-INF/lib 정도가 되고,

   클래스파일 디렉토리는 웹애플리케이션의 WEB-INF/classes 정도가 된다.

3. runFinder.bat를 실행한다.

   C:\> runFinder [클래스명 전체 또는 일부]

    단, 여기서 클래스명은 대소문자를 구분한다.

4. 생성되는 result.txt 파일을 열어 클래스들의 위치를 확인한다.


프로젝트마다 lib.properties 하나만 세팅해 놓으면, 끝날 때까지 편리하게 사용할 수 있을 것이다.

클래스 중복 확인 프로그램과 형식이 똑같으므로 같은 디렉토리에 놓고 공유해서 사용해도 괜찮다.



이것도 역시, 아무쪼록 많은 도움이 되길...


추가>

이것도 원래 JDK1.5에서만 돌아가서 추가로 1.4로 컴파일한 프로그램을 올립니다.


AND

놀라운 발견

Java_Web 2007. 8. 12. 02:09

오늘 코딩을 하다가 놀라운 사실을 발견했다.

아래와 같은 코드를 디버깅용으로 만들어 넣고 테스트해 보았다.

 

System.out.println("ignore:"+ignore+",characterencoding:"+request.getCharacterEncoding());

 

그런데, 분명히 콘솔에 찍혀야 되는데 안 찍히길래 컴파일이 제대로 된 건가 확인하기 위해 디컴파일러로 소스를 다시 보니 아래와 같은 코드가 보이는 것이다.

 

System.out.println((new StringBuilder("ignore:")).append(ignore).append(",characterencoding:").append(request.getCharacterEncoding()).toString());

 

흠, String concatenation 때문에 하도 문제가 생기니 JDK 1.5부턴 컴파일할 때 아예 이렇게 바이트코드를 만드는 모양이군...

요 몇달동안 String concatenation해야 할 게 많아서 그때마다 StringBuffer에 append하느라고 눈 빠질 뻔 했는데, 이게 언제 바뀐 거야.

바꾸면 나한테 전화라도 미리 해 줬어야 되는 거 아닌감? ㅋㅋ

 

AND

한동안 X-Internet 프로젝트를 하다 보니 순수 웹 개발에 대해서 잘 몰랐었는데

올해 순수 웹 개발을 하다 보니 말로만 듣던 Firefox + Firebug의 기능을 확인하게 되었다.

진작 이런 게 있었으면 웹개발 진짜 쉽게 할 수 있었는데, 왜 이제야 나온 거니? 왜 그런 거니?

 

1. Firebug 설치

Firefox만으로는 안 되고, Firebug라는 플러그인을 추가해야 강력한 무기를 완성하게 되는 것이다.

Firefox의 메뉴에서 "도구 > 부가기능"으로 들어간다.

 

사용자 삽입 이미지

 

이 다이얼로그는 이미 설치되어 있는 것이고, 없다면 아래의 "유용한 확장 기능 찾기"로 들어가 Firebug를 찾아 설치해야 한다.

설치되면 위와 같은 다이얼로그를 볼 수 있다.

설치된 후에 Firebug와 관련된 설정은 "도구 > Firebug"에서 조정할 수 있는데, Firefox를 오직 개발용으로 사용한다면 문제가 없지만 웹서핑용으로도 사용한다면 자신이 디버그를 원하는 주소를 등록하는 것이 좋다. 아무래도 디버깅툴이다 보니 Firebug가 동작하면 사이트가 뜨고 동작하는데 시간이 좀 걸린다.

 

 

2. Inspect Element

나를 반하게 한 기능 중의 하나가 Inspect Element이다. 이건 특정 element의 현재 속성을 HTML로 표현해 준다. 중요한 건 자바스크립트 등으로 변경되거나 추가된 각종 속성을 모두 보여 준다는 것이다. 그러니까, 서버에서 받은 코드가 아닌 현재 웹브라우저가 갖고 있는 실제 내용을 직접 확인할 수 있다는 얘기다.

 

이것은 화면상의 특정 부분에 오른쪽 클릭을 하고 메뉴에서 "Inspect Element"를 선택한다.

 

사용자 삽입 이미지

 

여기서는 맨 위의 플러스 이미지에서 오른쪽 클릭을 했다.

그러면, Firefox 하단에 아래와 같은 내용이 나타난다.

 

사용자 삽입 이미지

 

왼쪽 부분에는 현재 메모리상의 HTML 코드가 나오고, 오른쪽에는 이 element에 적용된 스타일이 표시된다.

HTML 코드에 마우스를 올려 놓으면 그 코드가 화면에서 어떤 부분인지 화면에 하늘색으로 표시가 되니 코드가 실제 화면에서 어떻게 나타나는지 확인하는 데도 유용하다.

 

 

3. 자바스크립트 디버그

이리저리 Firebug를 사용해 보다가 가장 놀란 기능이다. 자바스크립트를 디버그하다니...

먼저 위의 그림에서 Script 탭을 선택하고, 바로 위에서 디버그할 js나 자바스크립트를 포함한 html을 선택하면 아래에 코드가 나타난다.

코드에서 실행을 멈출 설정할 라인을 골라 클릭하면 breakpoint가 표시된다.

여기서 화면의 버튼을 클릭해서 자바스크립트를 실행시키거나, 화면을 다시 로딩하거나 하면 설정해 놓은 breakpoint에서 멈춰서 다음과 같은 화면이 나타난다.

 

사용자 삽입 이미지

 

여기부터는 이클립스에서 디버그를 해 본 사람이라면 편하게 사용할 수 있다.

오른쪽에 변수의 값들을 확인할 수 있고, New watch expression...에서 표현식을 입력하고 중간중간 확인해 볼 수도 있다.

프로그램 진행은 오른쪽 위의 각종 화살표를 누르면서 진행해 볼 수 있다. 단, 이클립스와 모양은 같지만 기능이 다르니 잘 확인해서 눌러야 한다.

 

 

이 포스트에선 내가 가장 유용하다고 생각되는 기능만을 다뤘는데 그 외의 버튼을 눌러보다 보면 정말 강력한 플러그인이라는 걸 느끼게 될 것이다.

단, Firefox는 IE에서 사용하는 비표준 태그나 자바스크립트 함수, ActiveX 등이 동작하지 않으므로 제한이 있다고 할 수도 있는데, 요즘 세상의 흐름이 표준을 준수하는 모든 브라우저를 사용할 수 있도록 사이트를 구성하는 것이기 때문에 이 기회에 이런 흐름을 따르는 것도 좋을 것 같다.

'Java_Web' 카테고리의 다른 글

클래스 위치 찾아 주는 프로그램  (0) 2007.08.15
놀라운 발견  (0) 2007.08.12
프린트 관련 CSS 속성  (0) 2007.06.14
중복 클래스 확인 프로그램  (0) 2007.05.08
JVM Monitoring  (0) 2007.04.14
AND

화면을 개발하다 보면 출력해야 하는 페이지가 꼭 있기 마련이다.

그런데, 통프레임이거나 프레임이 분리되는 경우라도 화면에는 보여야 하지만 출력할 때는 빼고 싶은 내용이 있다.

이거 찾는 데 시간이 걸리긴 했는데, 막상 적용하기는 무척 간단하다.

 

아래의 내용을 HTML의 style 태그 내에 넣거나, include하는 CSS 파일에 넣는다.

@media print
{

  .noprint { display:none; }

}

 

설명 : @media print 는 print되는 결과물에만 적용되는 스타일이라는 뜻이다.

        .noprint { display:none; } 잘 아는 바와 같이 display:none은 영역을 차지하지 않고, 보여주지도 않는다.

        결과적으로 noprint라는 스타일을 적용한 객체는 프린트할 때 제외된다는 뜻이다.

 

이렇게 선언이 되었으니 적용만 하면 된다.

table, tr, td, div, input 등 어떤 객체든 일반 스타일 적용하듯class="noprint"속성만 붙이면 출력할 때 제외된다.

만약에 그 객체에 이미 화면용 스타일이 적용되어 있다면,

적용된 화면용 스타일이 "input_text"라면 그냥 그 옆에 noprint만 추가해 주면 된다.

다음과 같이class="input_text noprint"하면 된다.

그리고, 자바스크립트로 window.print()만 실행하면 noprint 속성이 적용 안 된 내용만 프린터로 출력된다.

이것을 응용하면 @media print 내에 프린트용 폰트나 속성을 적용해서, 화면과 출력물의 모양을 달리 할 수도 있다.

하지만, 이런 귀찮은 작업을 누가 하겠는가? 하라고 하면 짜증날 것 같다. ^^;

 

 

참고로 아래에는 window.print()로 인쇄 다이얼로그가 떴을 때 기본 종이 방향이 가로가 되도록 하는 CSS이다.

화면 내용의 폭이 커서 가로 출력이 필요할 때 유용하다.

(그런데, IE6에선 동작하고, FireFox2에선 동작 안 한다. FireFox는 세로로 해도 알아서 넘어가지 않게 자동축소출력해 주니 문제없다.)

이것도 마찬가지로 HTML의 style 태그 내에나, include하는 CSS 파일 내에 추가시켜 주면 된다.

@page { size: landscape; }

 

'Java_Web' 카테고리의 다른 글

놀라운 발견  (0) 2007.08.12
웹개발을 위한 Power Tool - Firefox + Firebug  (0) 2007.08.04
중복 클래스 확인 프로그램  (0) 2007.05.08
JVM Monitoring  (0) 2007.04.14
Query Generator  (1) 2007.01.30
AND

WAS에 jar 파일과 class 파일들을 만들어 올려서 사용하다 보면, 개발할 땐 잘 돌아갔는데 서버에서 에러가 나는 경우가 많다.

클래스로더의 상하구조 때문일 경우도 있고, 동일한 패키지의 동일한 클래스가 여러 버전으로 중복되어 올라가 있어 발생하는 경우도 있다.

그래서, jar 파일과 class 파일이 있는 디렉토리만 입력해 주면 포함된 모든 클래스 파일을 뒤져서 중복여부를 체크해 주는 프로그램을 만들어 보았다.

 

사용법 :

1. 첨부된 zip 파일의 압축을 푼다.

2. lib.properties에 WAS 동작시 로딩되는 jar 파일 디렉토리(lib)와 class 파일 디렉토리(classes)를 모두 입력한다.

   jar를 포함한 디렉토리는 jar로 시작해서 일련번호를 붙이고, class파일을 포함한 디렉토리는 class로 시작해서 일련번호를 붙인다.

   단, 절대경로로 입력하며 경로구분자는 반드시 "/"로 해야 한다. "\"일 경우는 바꿔 주어야 한다.(이건 귀차니즘 때문에.. ^^;)

3. runChecker.bat를 실행한다.

4. 생성되는 result.txt 파일을 열어 중복 클래스와 클래스들의 파일크기, 생성일자를 비교해 어떤 걸 빼야 할지 결정한다.

 

아무쪼록 많은 도움이 되길...

 

추가>

기존에 올렸던 프로그램이 JDK1.5에서만 돌아가기 때문에

추가로 JDK1.4를 사용하는 분들을 위한 프로그램을 첨부합니다.

 

'Java_Web' 카테고리의 다른 글

웹개발을 위한 Power Tool - Firefox + Firebug  (0) 2007.08.04
프린트 관련 CSS 속성  (0) 2007.06.14
JVM Monitoring  (0) 2007.04.14
Query Generator  (1) 2007.01.30
Unix에 CVS 서버 설치 & 이클립스 연결  (0) 2007.01.06
AND

JVM Monitoring

Java_Web 2007. 4. 14. 00:44

J2SE 5.0부터 JVM 상태를 모니터링할 수 있는 기능이 제공된다.

대강 보면 JMX 방식으로 처리되는 것 같고, 메모리를 비롯해 쓰레드, 클래스 로딩까지 볼 수 있어 문제를 찾아내야 할 경우에 꽤 유용하게 사용될 수 있을 것 같다.

WebLogic 같은 경우 8.1에선 콘솔에서 Heap Memory 모니터링 기능이 있어서 사용했는데, 9.0에서는 없어진 것인지 찾을 수가 없었다.

있다 하더라도 지금부터 설명하는 걸로 하면 더 많은 정보를 세세히 살필 수 있으니 신경 안 쓰려고 한다. ㅋㅋ

 

1. JVM에 자바 옵션 추가

-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port={포트번호}
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false

☞ 여기서 {port번호}는 외부에서 이 WAS에 접속하기 위한 포트로 보이고, netstat으로 쳐 봐서 사용하지 않는 포트번호를 골라서 사용하면 될듯하다. 대강 10000~15000번에서 고르면 되겠고, 참고로 나는 12000번을 사용했다.

 

이 옵션을 적용시키려면 이클립스 같은 데서 디버그모드로 WAS를 띄운다면 Server정보의 start탭에 VM Arguments 부분에 붙여 넣으면 되고, 스크립트 방식으로 구동한다면 한 줄로 몰아서 %JAVA_OPTION 변수에 추가시켜 주면 되겠다.

set JAVA_OPTS=%JAVA_OPTS% -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=12000 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false

-> 위는 jBoss에서 사용한 예

 

2. 1.에서 적용한 옵션을 적용한 WAS 기동

 

3. {JDK_Home_Directory}/bin/jconsole.exe를 실행

사용자 삽입 이미지

나는 WAS를 로컬에서 띄워서 그런지 Local탭에 자동으로 인식이 되었고 Connect 버튼을 클릭하면 바로 연결된다.

Remote 탭이 있는 걸 보니 원격의 WAS에도 연결이 가능한 것으로 보이나 테스트를 못 해 봤으니 일단 패스~(나중에 해 보고 추가하겠음)

 

4. 연결 후 JVM 정보 모니터링

사용자 삽입 이미지

일단 전체적인 내용을 간추려서 보여 준다.

 

사용자 삽입 이미지

Heap, Non-Heap 별로 모니터링이 가능하고, 오른쪽 아래의 이미지를 클릭하면 그 중에서도 eden, survivors, perm 등등의 영역별로 모니터링을 할 수 있다. Perform GC를 클릭하면 GC도 한 번 시켜 볼 수 있다.

 

사용자 삽입 이미지

쓰레드 정보도 모니터링이 가능하다.

 

사용자 삽입 이미지

로딩된 클래스의 수도 확인이 가능하다.

 

사용자 삽입 이미지

Mbean 정보도 볼 수 있다.

 

사용자 삽입 이미지

JVM 및 시스템에 관한 정보까지 쭉~ 확인시켜 준다.

 

돈 주고 비싼 툴 사서 보면 더 좋겠지만, 여건이 안 된다면 이런 것도 도움이 되지 않을까 싶다.

 

'Java_Web' 카테고리의 다른 글

웹개발을 위한 Power Tool - Firefox + Firebug  (0) 2007.08.04
프린트 관련 CSS 속성  (0) 2007.06.14
중복 클래스 확인 프로그램  (0) 2007.05.08
Query Generator  (1) 2007.01.30
Unix에 CVS 서버 설치 & 이클립스 연결  (0) 2007.01.06
AND

Query Generator

Java_Web 2007. 1. 30. 07:18



항상 SQL 쿼리를 만드는 일은 단순반복적인 일이다.
그래서, 간단한 프로그램을 만들어 보았다.
위에 첨부한 querygen.war만 deploy하면 되고, 아래의 사용법대로 사용하기만 하면 된다.
단, Oracle 전용이고, 포함된 JDBC 드라이버(ojdbc14.jar)는 10g 버전용이므로 8i, 9i 까지 모두 이상 없을 것이나, 이후에 나오는 버전에서는 안 될 수도 있으니 그 때는 오라클 홈페이지에서 새로운 버전의 드라이버를 다운로드해 사용하길 바란다.
 
 
사용자 삽입 이미지

querygen이라는 context path로 deploy하면 위와 같이 입력하면 화면이 뜬다.

그리고 ,'커넥션정보 표시' 부분을 클릭하면 위와 같이 커넥션 정보가 나타난다.

여기서 IP, Port, SID, ID, Password 등을 입력하면 연결준비가 끝나는 것이다.

단, 이렇게 입력한 정보는 쿠키에 저장되니 다음에 접속해도 이전에 사용했던 정보가 나타난다. 혹시 ID, PW가 저장되지 않길 원한다면 쿠키 부분 코드를 지워서 사용하면 된다.
 

사용자 삽입 이미지


1. 테이블명 일부를 입력하고 '검색' 버튼을 클릭하거나, '전체테이블검색' 버튼을 클릭하면 아래쪽 프레임(②)에 테이블 및 테이블주석 리스트가 나타난다.

2. ②에서 테이블을 선택하고 '컬럼정보' 버튼을 클릭하면 오른쪽 아래와 같은 팝업창에 테이블에 관한 상세한 정보가 나타난다.

3. ②에서 테이블을 선택하고 'SQL 생성' 버튼을 클릭하면 오른쪽 프레임(⑤)에 해당 테이블의 CRUD 쿼리가 생성되어 나타난다.


필요에 따라 적당히 고쳐서 쓰시길...


'Java_Web' 카테고리의 다른 글

웹개발을 위한 Power Tool - Firefox + Firebug  (0) 2007.08.04
프린트 관련 CSS 속성  (0) 2007.06.14
중복 클래스 확인 프로그램  (0) 2007.05.08
JVM Monitoring  (0) 2007.04.14
Unix에 CVS 서버 설치 & 이클립스 연결  (0) 2007.01.06
AND

얼마전 CVS 서버를 설치할 일이 있었는데 하필 OS가 HP-UX였다. CVS가 오픈소스여서 그런지 리눅스에 설치하는 가이드는 많지만, Unix에 설치하는 가이드는 정말 찾아 보기 힘들었다. 맨땅에 헤딩하며 물어물어 겨우 설치를 하고는 혹시 나와 같이 고민하는 분들을 위해서 정리된 가이드를 공유하고자 한다.

 

<가이드 전제조건>
- 서버OS : HP-UX 11i
- cvs 실행파일이 있는 디렉토리 : /cvs
- cvs root 디렉토리 : /cvs/repository
- cvs용 사용자 계정 : cvs

☞ 혹시 다른 OS라도 해당 OS에 맞는 명령어로 다음의 과정을 진행하면 된다.

 

 

1. cvs 계정을 생성한다(root 계정으로 실행)

    ☞ CVS 서버를 실행하고 ,관련 디렉토리에 대한 권한을 갖는 계정을 생성한다.


  $ useradd cvs

  cvs 계정 생성


  
$ passwd cvs

  cvs 계정에 대한 암호 설정

 

 

2. /cvs 이하 디렉토리의 권한을 cvs 계정에게 준다(root 계정으로 실행)

    ☞ cvs 계정이 CVS서버 실행명령을 수행하고, repository의 파일을 읽을 수 있도록 권한을 부여한다.


  
$ chown -R cvs /cvs

   cvs 계정에게 /cvs 디렉토리 이하 디렉토리에 대한 소유권 부여

 

 

3. cvs 서버 실행파일 다운로드 후, /cvs 폴더에 업로드(cvs 계정으로 실행)

    ☞ OS에 적합한 CVS 실행파일을 다운로드해 서버에 업로드한다. 컴파일된 실행파일이 아닌 소스코드를 다운로드했을 경우, 서버에서 컴파일 작업이 필요하다.

 

   -www.cvshome.org에서 cvs 실행파일(binary) 다운로드(cvs-1.11.21-HP.bin.gz)한다.

      stable 버전 중에 가장 높은 버전을 선택하는 것이 좋다.

   - 알집으로 압푹을 해제한다.  -> cvs-1.11.21-HP.bin
   - ftp프로그램으로 cvs-1.11.21-HP.bin 파일을 /cvs 폴더에 업로드한다.

     (ftp 로그인시 당연히 cvs 계정을 사용한다.)

   - cvs-1.11.21-HP.bin 파일명을 cvs로 변경한다. ->$ mv cvs-1.11.21-HP.bin cvs
   - cvs파일을 실행가능하도록 변경한다. ->
$ chmod 744 cvs

 

 

4. cvs 계정의 .profile에 CVSROOT 환경변수 등록 및 cvs 실행파일이 있는 디렉토리를 PATH에 추가(cvs 계정으로 실행)

    ☞ CVS 서버 기동시 필요한 환경을 설정하는 과정이다.

 

   완전 Unix 초보를 위한 가이드 ^^;

  $ cd   cvs 계정의 홈디렉토리로 이동

  $ vi .profile   cvs 계정의 환경설정파일(.profile) 파일 열기


   .profile 파일에 아래의 두 라인을 아랫쪽에 추가(OS에 따라 형식이 다를 수 있음)

 PATH=$PATH:/cvs:.
 export CVSROOT=/cvs/repository
  
   수정된 내용을 저장한 다음,

  $ .profile실행해 새로운 환경을 적용한다.

 

 

5. 레파지토리 구성(cvs 계정으로 실행)

    ☞ CVS에서 데이터를 저장할 레파지토리를 구성하는 과정이다.

 

  $ cvs -d /cvs/repository init
   /cvs/repository 아래에 CVSROOT 라는 디렉토리 생성되고, 그 안에 관련 파일들도 자동 생성된다.

 

 

6. (pserver 인증 방식을 위한) passwd 파일 생성 및 사용자 추가(cvs 계정으로 실행)

    ☞ CVS서버에 접속하는 클라이언트 인증을 위하여 아이디와 패스워드를 저장하는 과정으로, cvs라는 하나의 Unix 계정을 이용하여 passwd라는 파일 안의 정보만으로 인증하는 pserver 인증방식만을 설명한다.

 

   - /cvs/repository/CVSROOT에 passwd라는 파일 생성(기본적으로 파일이 없다)
   - htpasswd라는 명령을 이용하여 사용자(cvs client)와 암호화된 패스워드 생성

     (이 명령을 실행했을 때 없다면, find 명령으로 찾는다)
    $ htpasswd -nb tom 123   -> htpasswd -nb [ID] [password]
     위의 명령은 'tom'이란 아이디에 '123'이라는 패스워드를 사용하겠다는 명령이다.

     그러면 아래와 같은 결과가 화면에 보인다.

     tom:7gSK6kHT4RJ.A

     (같은 패스워드를 반복 실행해도 다른 결과가 나오나 인증에는 문제가 없다 ^^)

 

   - 위의 내용을 터미널에서 복사한 다음, 그 뒤에 :cvs(Unix 사용자계정)를 붙여서 위에서 만든 passwd라는 파일에 차례로 사용자당 한 라인씩 추가시킨다. 생성할 클라이언트 아이디가 많고, 패스워드를 잃어버릴 때마다 관리하기가 귀찮다면 그냥 동일한 암호화된 패스워드를 복사해서 붙여 넣어도 상관없다. 다음은 그 예다.
    $ cat passwd
    tom:7gSK6kHT4RJ.A:cvs
     
ann:7gSK6kHT4RJ.A:cvs

     이렇게 되면 'tom'과 'ann'이란 아이디에 '123'이라는 패스워드를 사용할 수 있다.

 

 

7. cvs server에 remote access를 위한 환경 설정(root 계정으로 실행)

    ☞ CVS 서버가 원격 클라이언트의 접속을 받을 수 있도록 포트를 설정하는 과정이다. 중간에 방화벽이 있을 경우에는 네트웍 담당자에게 방화벽의 포트도 열어 주도록 요청해야 한다.(방화벽은 잘 몰라서 패스 ^^;)


   - /etc/services 파일에 아래의 줄 추가(2401 포트로 tcp 서비스 등록)
     cvspserver 2401/tcp

      추가하기 전 이 포트가 다른 서비스에 등록되지 않았나 미리 확인하고, 사용중이면 다른 포트를 사용해야 한다.


   - /etc/inetd.conf 파일에 아래의 줄 추가(CVS 서비스가 등록되어야 함)
     cvspserver stream tcp nowait root/cvs/cvscvs--allow-root=/cvs/repositorypserver

 

    ->/cvs/cvs: /cvs 디렉토리의 cvs 실행파일

    ->cvs: 위의 cvs 실행파일을 실행하는 Unix 계정
    ->/cvs/repository: CVS ROOT 디렉토리

    나머지 설정에 관한 내용은 Unix를 잘 모르는 관계로 패스~

 

 

8. 7.에서 설정한 환경 적용(root 계정으로 실행)

    ☞ 설정준비가 다 되었으니, 그것을 실제로 적용하는 과정이다.

 

  $ ps -ef | grep inetd
   이 명령을 이용해 inetd의 프로세스ID 확인


  $ kill -HUP [inetd 프로세스ID]
   inetd 데몬 재기동. 이렇게 하면 설정한 내용이 실제로 적용된다.

   한방에 kill -HUP inetd 형태로 적용하면 좋으나, HP-UX는 프로세스ID로 처리해야 하는 모양이다.

 

 

9. 이클립스에서 cvs 연결

    ☞ 다른 CVS 클라이언트도 가능하겠지만, 일단 이클립스로 설명한다.


   [CVS Repository Exploring] Perspective를 Open한다
   New > Repository Location 선택
   - Host : cvs가 설치된 서버의 IP
   - Repository Path(CVSROOT) : /cvs/repository
   - User : tom (6.에서 생성한 아이디)
   - Password : 123 (6.에서 사용한 패스워드)
   - Connection type : pserver
   - Use Default Port : 선택(7.에서 설정한 2401 포트)

      (7.에서 2401 외에 다른 포트를 사용했다면 그 포트를 직접 입력한다)


   위와 같이 입력한 후 Finish 버튼을 클릭하면 연결된다.

 

 

 

나름대로 삽질하면서 배운 정보 열심히 전달하려고 노력했는데, 많은 도움이 되시길...

 

'Java_Web' 카테고리의 다른 글

웹개발을 위한 Power Tool - Firefox + Firebug  (0) 2007.08.04
프린트 관련 CSS 속성  (0) 2007.06.14
중복 클래스 확인 프로그램  (0) 2007.05.08
JVM Monitoring  (0) 2007.04.14
Query Generator  (1) 2007.01.30
AND