'Java'에 해당되는 글 23건

  1. 2009.07.14 Http 분석 프로그램
  2. 2009.07.14 HTTP 패킷 분석 방법론
  3. 2009.07.14 UI 개발자를 위한 북마크
  4. 2009.03.30 [Tip]모든 폼 데이터 출력하기
  5. 2009.03.17 메소드 시그너처(method signature) 란?
  6. 2009.03.17 SQLJ란?
  7. 2009.01.16 Java 프로젝트 배포하기 - JSmooth, InstallFactory
  8. 2009.01.16 jar파일에서 외부 패키지 사용하기
  9. 2009.01.15 JVM 메모리 구조 및 설명
  10. 2009.01.15 [JVMSTAT]jvmstat 3.0 설치방법
2009. 7. 14. 07:28

Http 분석 프로그램

2009. 7. 14. 07:19

HTTP 패킷 분석 방법론

2009. 7. 14. 06:53

UI 개발자를 위한 북마크

2009. 3. 30. 18:38

[Tip]모든 폼 데이터 출력하기

여기서는 모든 파라미터 이름을 찾아 표로 만드는 프로그램을 살펴 본다. 이 프로그램은 여러 개의 값을 갖는 파라미터 뿐 아니라 ‘0' 값을 갖는 파라미터도 강조된 문자로 출력해준다. 먼저 ‘HttpServletRequest ‘의 ‘getParameterName' 메소드를 통해 파라미터 이름을 구한다. 다음으로 계속 ‘Enumeration'을 순환하면서 언제 끝낼지 판단하기 위해 ‘hasMoreElement'를 사용하고, 각 값을 얻기 위해 ‘nextElement'를 사용한다. ‘nextElement'는 ‘Object'를 반환하기 때문에 ‘Strings' 배열의 요소를 하나씩 ‘String'으로 변환해서 ‘getParameterValues'로 넘겨준다. 만약 그 배열에 하나의 엔트리만 있고 빈 문자열만 있다면 파라미터는 값을 갖지 않는 것이기 때문에 서블릿에서는 ‘No Value'를 이탤릭 체로 출력하게 했다. 만약 배열에 1개 이상의 엔트리가 있다면 그 파라미터는 여러 개의 값을 갖기 때문에 점으로 된 목록으로 각기 그 값을 출력하게 한다. 이외의 경우는 표에 값이 출력되도록 했다.
소스 다운로드

여기서는 이전에 만든 ServletUtilities.java 를 사용한다.

package hall;

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.util.*;

/** Shows all the parameters sent to the servlet via either
* GET or POST. Specially marks parameters that have no values or
* multiple values.
*

* Part of tutorial on servlets and JSP that appears at
* http://www.apl.jhu.edu/~hall/java/Servlet-Tutorial/
* 1999 Marty Hall; may be freely used or adapted.
*/

public class ShowParameters extends HttpServlet {
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
String title = "Reading All Request Parameters";
out.println(ServletUtilities.headWithTitle(title) +
"<BODY BGCOLOR=\"#FDF5E6\">\n" +
"<H1 ALIGN=CENTER>" + title + "</H1>\n" +
"<TABLE BORDER=1 ALIGN=CENTER>\n" +
"<TR BGCOLOR=\"#FFAD00\">\n" +
"<TH>Parameter Name<TH>Parameter Value(s)");
Enumeration paramNames = request.getParameterNames();
while(paramNames.hasMoreElements()) {
String paramName = (String)paramNames.nextElement();


out.println("<TR><TD>" + paramName + "\n<TD>");
String[] paramValues = request.getParameterValues(paramName);
if (paramValues.length == 1) {
String paramValue = paramValues[0];
if (paramValue.length() == 0)
out.print("<I>No Value");
else
out.print(paramValue);
} else {
out.println("<UL>");
for(int i=0; i<paramValues.length; i++) {
out.println("<LI>" + paramValues[i]);
}
out.println("</UL>");
}
}
out.println("</TABLE>\n</BODY></HTML>");
} }


public void doPost(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
 


ShowParameters에서의 폼 처리
이것은 파라미터의 수를 이 서블릿으로 보내주는 HTML form이다. 소스 코드 링크 에서 오른쪽 클릭해서 HTML을 다운로드 할 수 있다. 이 링크에 왼쪽 클릭을 하면 온라인 상에서 테스트를 할 수 있다. 여기서는 데이터를 보내기 위해 POST를 썼다 (PASSWORD 를 포함한 모든 폼을 보내야 하기 때문이다). 서블릿이 가지는 값은 ‘doGet'과 ‘doPost'를 모두 포함한다. 하지만 단순히 살펴보기만 하려면 GET을 사용한 버전 을 다운로드 하거나 온라인 상에서 테스트할 수 있다.

PostForm.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<TITLE>A Sample FORM using POST</TITLE>
</HEAD>

<BODY BGCOLOR="#FDF5E6">
<H1 ALIGN="CENTER">A Sample FORM using POST</H1>
<FORM ACTION="/servlet/hall.ShowParameters"
METHOD="POST">
Item Number:
<INPUT TYPE="TEXT" NAME="itemNum"><BR>
Quantity:
<INPUT TYPE="TEXT" NAME="quantity"><BR>
Price Each:
<INPUT TYPE="TEXT" NAME="price" VALUE="$"><BR>
<HR>
First Name:
<INPUT TYPE="TEXT" NAME="firstName"><BR>
Last Name:
<INPUT TYPE="TEXT" NAME="lastName"><BR>
Middle Initial:
<INPUT TYPE="TEXT" NAME="initial"><BR>
Shipping Address:
<TEXTAREA NAME="address" ROWS=3 COLS=40></TEXTAREA><BR>
Credit Card:<BR>
<INPUT TYPE="RADIO" NAME="cardType"
VALUE="Visa">Visa<BR>
<INPUT TYPE="RADIO" NAME="cardType"


VALUE="Master Card">Master Card<BR>
<INPUT TYPE="RADIO" NAME="cardType"
VALUE="Amex">American Express<BR>
<INPUT TYPE="RADIO" NAME="cardType"
VALUE="Discover">Discover<BR>
<INPUT TYPE="RADIO" NAME="cardType"
VALUE="Java SmartCard">Java SmartCard<BR>
Credit Card Number:
<INPUT TYPE="PASSWORD" NAME="cardNum"><BR>
Repeat Credit Card Number:
<INPUT TYPE="PASSWORD" NAME="cardNum"><BR><BR>
<CENTER>
<INPUT TYPE="SUBMIT" VALUE="Submit Order">
</CENTER>
</FORM>

</BODY>
</HTML>

2009. 3. 17. 13:50

메소드 시그너처(method signature) 란?

메소드의 특성과 메소드 이름, 파라미터, 반환값의 테이터타입을 가진 형태이다.
2009. 3. 17. 11:05

SQLJ란?

Sqlj 무엇인가?

개발자들은 기존의 C언어를 이용해서 Oracle Database 접근 하고자 가지 방식을 이용했다. 하나는 “Pro*C” 방식이고, 다른 하나는 “OCI Library” 바로 call하는 방식이었다. 가지의 차이점은 “Pro*C” 경우 Embedded Sql문을 이용하기 때문에 기존의 C문장에 다음과 같이 삽입함으로써 Oracle Database에서 데이터를 가공할 있었다.

EXEC SQL DELETE FROM dept WHERE deptno = :v_deptno

그러나 만약, OCI Library 직접 call해서 위와 같은 내용을 수행하려면 low level coding 필요한 , 이와 비교해 Java 경우에는 전자와 같은 방식이 “sqlj”방식이고 후자와 같은 low level programming “JDBC API” 이용하는 방식이라 있겠다.

Sqlj JDBC API 이용 방식의 장단점이 있겠지만, 다음 표로 간단히 확인해 보자.

 

 

SQLJ

JDBC API

코딩의

간결하다.

많은 line 필요

sql syntax 검사

Pre-compile time시에 결정

runtime시에 결정

Host 변수

사용 가능

사용 불가능

Dynamic Sql이용

불가능

사용 가능

 [1 SQLJ JDBC API 비교]

 

위에서 언급된 부분을 살펴보면 SQLJ JDBC API 바로 이용하는 것보다 코딩 line수가 적으며, 이것은 개의 column 값을 update 확실히 있다. SQLJ sql문을 pre-compile time시에 syntax objects 존재 여부 type 검사 등을 위해서 미리 database 접속을 검증을 한다. 그러므로, compile-time시에 에러를 발생시키고, runtime시에 에러를 줄임으로써, 개발자들로 하여금 빠르고 쉬운 debugging 가능토록 한다.

또한, SQLJ “Host variables” 이용할 있으므로, 문장이 상당히 간결해 있으나 JDBC API 이용할 경우에는 그렇지 못하다. 그러나, SQLJ 경우 compile시에 sql문이 완전히 조합되어 있어야 하므로, “dynamic sql”등을 사용할 수가 없다. 만약 dynamic sql 이용하고자 한다면, “JDBC API” 이용해서 Dynamic SQL 구현해야 한다.

정리를 하면, “Static SQL” 해당하는 부분은 SQLJ 이용하는 것이 좋고, Dynamic SQL 해당하는 부분은 “JDBC API” 이용함으로써 개발 생산성과, rumtime시의 performance 극대화할 있겠다.

2009. 1. 16. 09:28

Java 프로젝트 배포하기 - JSmooth, InstallFactory

JSmooth : Jar파일을 EXE 파일로 변환 --> http://jsmooth.sourceforge.net/
InstallFactory : 배포파일 만들기 --> 첨부파일

2009. 1. 16. 09:19

jar파일에서 외부 패키지 사용하기

사람이 밥만먹고 살 수는 없듯이, 프로그램을 짜다보면 외부 jar파일을 이용해야 하는 경우가

수시로 생기게 된다. 문제는, 내가 짠 프로그램을 jar파일로 배포해야 할때도 내가 사용했던

외부 jar파일이 필요하게 된다는 것이다.


내가 만든 jar파일에서 외부 jar파일을 사용해야 한다면 어떤 방법이 가장 좋을까..

내가 생각하기에는 내 jar파일을 만들때 외부 jar파일도 함께 묶고 Class-Path를 잘 지정해

주는것이 가장 좋은 방법이 아닐까 싶다. 이렇게 해놓으면 내 jar파일 내부에 있는 클래스들이

외부 jar파일을 참조할 수 있고, 외부 jar파일역시 내 jar파일 외부로 나와있어서 실수로 삭제되거나

하는 일이 발생하지 않는다.

그런데, 문제는 java의 jar파일은 이러한 기능을 지원하지 않는다는 것이다. 아래는 jar Document

부분의 Class-Path에 관한 내용의 일부이다.

 

===========================================================================

Note: The Class-Path header points to classes or JAR files on the local file system, not JAR

          files within the JAR file or classes on the network

=> Class-Path header 부분에는 사용자의 컴퓨터 내부의 class파일이나 JAR파일은 이용할

    있지만 JAR파일 내부, 또는 network 상의 JAR파일이나 class파일들은 사용할 수 없습니다.

===========================================================================

 

이 글에서 볼 수 있듯이 java에서는 jar파일 내부의 jar파일에 대해서 Class-Path를 지원해 주지

않는다. 즉, jar파일 내부에 외부 jar파일을 위치시켜 놓고 프로그램이 무난히 작동되기를 바랄 수

없다는 뜻이다.


그렇다면 어떻게 외부 jar파일을 이용할 수 있을까. 크게 두가지 방법이 있다.

1) 외부 jar파일의 압축을 풀고, 압축이 풀린 class들을 내 jar파일에 묶어버리는 방법

2) 외부 jar파일을 내 jar파일의 내부가 아닌 외부에 위치시켜 놓고 Class-Path를 설정하는 방법

2009. 1. 15. 11:16

JVM 메모리 구조 및 설명

JVM의 메모리 구조를 좀 알아둘 필요가 생겨서 찾아봤다.




응용프로그램이 실행되면, JVM은 시스템으로부터 프로그램을 수행하는데 필요한 메모리를 할당받고 JVM은 이 메모리를 용도에 따라 여러 영역으로 나누어 관리한다.
그 중 3가지 주요영역(Method Area, 호출스택, Heap)에 대해서 알아보도록 하자.



[참고] cv는 클래스변수, lv는 지역변수, iv는 인스턴스변수를 뜻한다.

1. 메소드영역(Method Area)
- 프로그램 실행 중 어떤 클래스가 사용되면, JVM은 해당 클래스의 클래스파일(*.class)을 읽어서 분석하여 클래스에 대한 정보(클래스 데이타)를 Method Area에 저장한다.
이 때, 그 클래스의 클래스변수(class variable)도 이 영역에 함께 생성된다.


2. 힙(Heap)
- 인스턴스가 생성되는 공간. 프로그램 실행 중 생성되는 인스턴스는 모두 이 곳에 생성된다. 즉, 인스턴스변수(instance variable)들이 생성되는 공간이다.

3. 호출스택(Call Stack 또는 Execution Stack)
호출스택은 메서드의 작업에 필요한 메모리 공간을 제공한다. 메서드가 호출되면, 호출스택에 호출된 메서드를 위한 메모리가 할당되며, 이 메모리는 메서드가 작업을 수행하는 동안 지역변수(매개변수 포함)들과 연산의 중간결과 등을 저장하는데 사용된다. 그리고, 메서드가 작업을 마치게 되면, 할당되었던 메모리공간은 반환되어 비워진다.
각 메서드를 위한 메모리상의 작업공간은 서로 구별되며, 첫 번째로 호출된 메서드를 위한 작업공간이 호출스택의 맨 밑에 마련되고, 첫 번째 메서드 수행중에 다른 메서드를 호출하게 되면, 첫 번째 메서드의 바로 위에 두 번째로 호출된 메서드를 위한 공간이 마련된다.
이 때 첫 번째 메서드는 수행을 멈추고, 두 번째 메서드가 수행되기 시작한다. 두 번째로 호출된 메서드가 수행을 마치게 되면, 두 번째 메서드를 위해 제공되었던 호출스택의 메모리공간이 반환되며, 첫 번째 메서드는 다시 수행을 계속하게 된다. 첫 번째 메서드가 수행을 마치면, 역시 제공되었던 메모리 공간이 호출스택에서 제거되며 호출스택은 완전히 비워지게 된다.
호출스택의 제일 상위에 위치하는 메서드가 현재 실행 중인 메서드이며, 나머지는 대기상태에 있게 된다.
따라서, 호출스택을 조사해 보면 메서드 간의 호출관계와 현재 수행중인 메서드가 어느 것인지 알 수 있다.
호출스택의 특징을 요약해보면 다음과 같다.


- 언제나 호출스택의 제일 위에 있는 메서드가 현재 실행 중인 메서드이다.
- 아래에 있는 메서드가 바로 위의 메서드를 호출한 메서드이다.


반환타입(return type)이 있는 메서드는 종료되면서 결과값을 자신을 호출한 메서드(caller)에게 반환한다. 대기상태에 있던 호출한 메서드(caller)는 넘겨받은 반환값으로 수행을 계속 진행하게 된다.

[예제6-6] CallStackTest.java
secondMethod()
class CallStackTest {
      public static void main(String[] args) {
            firstMethod();
      }

      static void firstMethod() {
            secondMethod();
      }

      static void secondMethod() {
            System.out.println("secondMethod()");            
      }
}
[실행결과]


위의 예제를 실행시켰을 때, 프로그램이 수행되는 동안 호출스택의 변화를 그림과 함께 살펴보도록 하자



(1)~(2) 위의 예제를 컴파일한 후 실행시키면, JVM에 의해서 main메서드가 호출됨으로써 프로그램이 시작된다. 이때, 호출스택에는 main메서드를 위한 메모리공간이 할당되고 main메서드의 코드가 수행되기 시작한다.
(3) main메서드에서 firstMethod()를 호출한 상태이다. 아직 main메서드가 끝난 것은 아니므로 main메서드는 호출스택에 대기상태로 남아있고 firstMethod()의 수행이 시작된다.
(4) firstMethod()에서 다시 secondMethod()를 호출했다. firstMethod()는 secondMethod()가 수행을 마칠 때까지 대기상태에 있게 된다. seoundMethod()가 수행을 마쳐야 firstMethod()의 나머지 문장들을 수행할 수 있기 때문이다.
(5) secondMethod()에서 println메서드를 호출했다. 이때, println메서드에 의해서 화면에 "secondMethod()"가 출력된다.
(6) println메서드의 수행이 완료되어 호출스택에서 사라지고 자신을 호출한 secondMethod()로 되돌아간다. 대기 중이던 secondMethod()는 println메서드를 호출한 이후부터 수행을 재개한다.
(7) secondMethod()에 더 이상 수행할 코드가 없으므로 종료되고, 자신을 호출한 firstMethod()로 돌아간다.
(8) firstMethod()에도 더 이상 수행할 코드가 없으므로 종료되고, 자신을 호출한 main메서드로 돌아간다.
(9) main메서드에도 더 이상 수행할 코드가 없으므로 종료되어, 호출스택은 완전히 비워지게 되고 프로그램은 종료된다.

[예제6-7] CallStackTest2.java

class CallStackTest2 {
      public static void main(String[] args) {
            System.out.println("main(String[] args)이 시작되었음.");
            firstMethod();
            System.out.println("main(String[] args)이 끝났음.");
     }
      static void firstMethod() {
            System.out.println("firstMethod()이 시작되었음.");
            secondMethod();
            System.out.println("firstMethod()이 끝났음.");            
     }

      static void secondMethod() {
            System.out.println("secondMethod()이 시작되었음.");
            System.out.println("secondMethod()이 끝났음.");            
     }

}
[실행결과]
main(String[] args)이 시작되었음.
firstMethod()이 시작되었음.
secondMethod()이 시작되었음.
secondMethod()이 끝났음.
firstMethod()이 끝났음.
main(String[] args)이 끝났음.



/// 또다른 아티클..

Java Virtual Machine의 메모리 관리

전통적인 C언어나 C++언어와는 달리 자바에서는 메모리 관리는 프로그래머가 일일이 하지 않고 JVM에서 알아서 관리 해 줍니다.(물론 닷넷의 경우엔 자바와 비슷한 방법으로 하지만)

메모리 관리란 크게 보면 생성/소멸(삭제, 반납)의 과정으로 생각 할 수 있는데 우리가 자바 프로그램에서 Hello h = new Hello(“방가방가”) 라고 하든지 아님 int i=10; 이라고 할 때 메모리의 일정 부분을 할당 받게 되는 것입니다. 메모리에서 할당이 필요해지면 JVM은 변수에 대해 실제의 내용을 포인터로써 관리를 해주게 됩니다. JVM이 모든 객체의 레퍼런스를(참조) 카운트하고 관리하기 때문에 메모리 영역의 충돌이나 삭제 하지 않은 메모리 때문에 memory leak등이 발생 할 가능성이 거의 없어 졌습니다.

HOT SPOT이전의 JVM(JIT기반, JDK1.3 이전)에서는 메모리에 대한 간접 참조 방식을 이용하였는데 아시는 것 처럼 간접 방식이므로 실제 내용을 찾아 가기 위해서는 두번이상의 참조가 일어나게 됩니다. 물론 조금은 느려질 소지가 있었겠지요~ 이 경우엔 오히려 Garbage Collection시에는 참조만 지우면 되므로 오히려 간단했다고 볼 수 있습니다.

간접 참조란 힙에 객체의 내용이 있다면 중간에 그곳을 가리키는 메모리 영역이 있고(핸들 메모리) 스택에 있는 변수가 핸들 메모리를 참조해서 실제 힙의 주소를 얻은 후 힙의 실제 내용을 참조하게 되는 방식 입니다. 반면 직접 참조의 경우 스택에 있는 변수가 힙메모리의 실제 주소를 가지고 있어 직접 참조 하게 되는 방식 입니다. 그러므로 자주 참조되는 변수나 객체가 있다면 직접 참조 방식이 훨씬 뛰어난 성능을 보입니다.

반면에 가비지컬렉션의 경우(메모리를 지우거나 참조값을 바꾸는 경우) 직접 참조 방식에서는 값이 없어지거나 사라져야 하는 변수에 대해 일일이 포인터를 지워줘야 합니다. 반면 간접 참조 방식의 경우 핸들 메모리만 수정을 해주면 되므로 오히려 간단해 지는 것입니다.

Virtual Machine에서는 스택과 힙 메모리를 사용하며 스택에는 프로그램에서 사용하는 변수, 함수명등이 수행 순서에 맞게 적재 되어 있고 힙 메모리에는 실제 스택에 있는 변수나 함수의 내용이 적재 됩니다. 즉 스택에는 실제 값이 존재하는 곳의 포인터를 가지므로 크기가 크지 않으나 힙의 경우 사용량이 커지게 됩니다. 만약 힙 메모리를 다써버린 다면 java.lang.OutOfMemory 오류가 발생 할겁니다.

이번에는 메모리의 해제에 대해 보도록 하겠습니다. 아까 위에서 만든 객체 참조변수에 대해 h = null; 이라고 하는 경우나 어떤 메소드 안에 쓰인 변수가 메소드의 실행이 종료하게 되는 경우에 메모리에서 해제 될 것 입니다.

JVM의 힙메모리에는 프로그램 실행시 생성된 여러 값들이 존재 합니다. 가비컬렉터가 하는 일은 이러한 힙 메모리중 사용하지 않는 메모리를 반환 시키는 역할을 하는 것입니다.  위의 경우 처럼 h = null; 이라고 명시적으로 지정 하는 경우 객체 헤더에 존재하는 GC(Garbage Collector) 필드가 값이 설정 됩니다. 이렇게 지정 된 객체에 대해 우선적으로 메모리에서 삭제를 하게 됩니다.

반면 스코프를 벗어나는 경우 Local 변수는 다음과 같은 조건에 따라 삭제 여부를 판단하게 됩니다. 스택 메모리에 있는 변수 중 해당 객체에 대한 참조가 있는 경우 또는 객체가 메모리에 있다는 이야기는 다음에 있을 확률이 높다는 판단(이게 LRU방식 맞나여??)을 JVM에서 해(일반적으로 프로그래밍에서 사용된 객체의 95% 이상이 생성된 후 곧 삭제된다는 가정 하에 아직까지도 있는 객체이므로 필히 중요한 것 일꺼야 하는 기술을 Generation Copying Collection이라 합니다) 가급적 가비지 컬렉션을 수행 하지 않습니다. 또는 정적 혹은 현재 스코프의 객체가 해당 객체를 참고 하고 있는 경우, JVM내부에서 사용하는 네이티브 메소드에 사용되는 객체에 해당 하는 경우 등은 가비지 컬렉션에서 제외를 하며 기타의 경우엔 메모리에서 삭제를 하게 됩니다. 대부분의 프로그래밍 언어에서 사용된 객체는 거의 금방 소멸 된다는 것 때문에 Java에서는 메모리를  두가지 영역으로 메모리를 나누는데 Young 영역과 Old 영역으로 나눕니다. Young 영역은 생긴지 얼마 안된 객체들을 저장하는 장소이고, Old영역은 생성된지 오래된 객체를 저장하는 장소 입니다. 각 영역의 성격이 다른 만큼 GC의 방법 또한 다릅니다. 또한 Perm 영역이라고 불리는 곳이 있는데 이곳에는 클래스나 메소드의 실행 코드가 저장 됩니다. 그래서 GC가 일어나는 곳은 old, new 영역이며 Perm영역은 GC가 수행 되지 않습니다.(소스 코드가 있으므로)

JDK1.3 이상에서 탑재된 HOT SPOT VM의 경우(병목 현상이 일어날 확률이 높은 부분을 먼저 컴파일) 가비지 컬렉션에 따른 성능 저하를 막기 위해 Generation Copying Collection 기술을 이용하여 가비지 컬렉션 대상을 줄였으며 Incremetal Pauseless 기법을 이용하여 가비지컬렉션 대상을 여러 개의 작은 그룹으로 나누어 확실히 삭제 가능한 객체부터 지워나가는 방식을 채택 했습니다. Incremetal Pauseless 기법에서는 1차 가비지 컬렉션 대상은 객체의 헤더에 GC 필드가설정된 것이고 2차 대상은 위의 4가지 유형에 속하지 않은 것 입니다. 2차 대상의 경우 일단 CG필드를 설정 하고 다음번 가비지 컬렉션 주기에 삭제 되는 것 입니다.
2009. 1. 15. 10:23

[JVMSTAT]jvmstat 3.0 설치방법

# java JVM Memory Perf 분석


- Tools : jvmstat-5.zip
   J2SE 1.5 이상


- 구성 환경 :
 Host A에 설치 동작중인 Java Applicaton( Unix )에 대한 메모리 이용율을
 Host B( Windows )에서 Remote로 확인


- Host A 설치내용
 J2SE 1.5 이상의 버젼이 설치 되었는지 확인
  참고 : Java 1.5부터는 jvmstat의 내용이 일부 포함되어 배포가 됨.

 jvmstat를 위한 Home Directory 생성 ( /usr/local/jvmstat )
 $ mkdir /usr/local/jvmstat/

 RMI Connection 권한 설정 파일 생성
 $ cd /usr/local/jvmstat/
 $ vi jstatd.all.policy
 grant codebase "file:${java.home}/../lib/tools.jar" {
     permission java.security.AllPermission;
 };

 jvmstat를 위한 환경 변경 설정
 $ export JAVA_HOME=/usr/local/java
 $ export JVMSTAT_HOME=/usr/local/jvmstat
 $ export PATH=$JVMSTAT_HOME/bin:$JAVA_HOME/bin:$PATH

 jstatd 실행 ( jvmstat 2.0의 perfagent와 같음. )
 $ cd /usr/local/jvmstat/
 $ cat start.sh
 #!/bin/bash

 export JVMSTAT_HOME=/usr/local/jvmstat
 export JAVA_HOME=/usr/local/jdk1.5.0_02
 export PATH=$JAVA_HOME/bin:$JVMSTAT_HOME:$PATH

 # RMI Registry Start
 $JAVA_HOME/bin/rmiregistry &

 # JSTAT PerfAgent Start
 nohup \
 $JAVA_HOME/bin/jstatd \
 -J-Djava.security.policy=$JVMSTAT_HOME/jstatd.all.policy \
 -J-Djava.rmi.server.logCalls=true \
 &
 $ sh start.sh

 local test 수행
 $ jps
 $ jstat -gcutil 11216 1000 10   ( 11216은 jvmps에서 vmid )

 Java RMI Connection을 위한 설정
 $ vi /etc/hosts
 위 hostname ( backup )을 RMI로 호출될 Interface의 IP로 변경 한다.
 127.0.0.1       localhost.localdomain localhost
 192.168.1.117 backup


- Host B 설치 내용
 J2SE 1.5 이상의 버젼이 설치 되었는지 확인

 jvmstat-3.zip를 C:\에 압축 풀기 ( visualgc에 대한 내용만이 포함되어 있음. )

 jvmstat를 위한 환경 변경 설정
 SET JAVA_HOME="C:\Program Files\Java\jdk1.5.0_02"
 SET JVMSTAT_HOME="C:\jvmstat"
 SET JVMSTAT_JAVA_HOME="C:\Progra~1\Java\jdk1.5.0_02"
 SET PATH=%JVMSTAT_HOME%\bat;%JAVA_HOME%\bin;%PATH%

 remote test 수행 ( Host A와의 RMI 통신여부 확인 )
 C:\jvmstat\bat\> jps 192.168.1.117
 C:\jvmstat\bat\> jstat -gcutil rmi://11216@192.168.1.117 1000 10


- Host A의 Java Application 모니터링
 상기의 설치 내용이 정상적으로 완료 확인

 Host B에서
 C:\jvmstat\bat\> visualgc 11216@192.168.1.117:1099 5000
  11216 : vmid
  192.168.1.117 : host A's IP Address
  1099 : Host A's RMI TCP Port
  5000 : Interval , millisecond