개발/자바 | Posted by 은우 아빠 2009. 1. 16. 10:08

Java (j2se 1.4.1) 메모리 영역 구조


출처 : http://cafe.naver.com/ArticleRead.nhn?articleid=69&sc=e0d433130b4a2d9c18&query=gc+java+%B8%DE%B8%F0%B8%AE&clubid=10092843

1. Sun Microsystyems의 자바 HotSpot VM은 힙을 세 개의 영역으로 나누고 있다.
 힙의 세 영역은 다음과 같다:
 1) Permanent space: JVM 클래스와 메소드 개체를 위해 쓰인다.
 2) Old object space: 만들어진지 좀 된 개체들을 위해 쓰인다.
 3) New object space: 새로 생성된 개체들을 위해 쓰인다.

New object space는 세 부분으로 다시 나누어진. 
모든 새로 생성된 개체들이 가는 Eden, 그리고 그 개체들이 나이들게(Old) 되기 전에 가는 Survivor space1(From), Survivor space2(To) 가 있다.

 

2. Garbage Collector
프로그램은 프로그램을 진행하면서 데이터들을 저장하는 것이 필요하다. 
데이터들은 모두 메모리에 저장이 되는데, 저장할 데이터가 있으면 메모리의 일정 공간을 할당받아서 사용하게 된다. 
프로그램 내에서 사용하게 되는 메모리를 'heap'이라고 한다. 
더 이상 사용되지 않는 데이터에게 메모리를 계속 할당해 주는 것은 메모리를 낭비하는 것이므로, 그 데이터가 사용하던 메모리를 회수하는 것이 필요하다. 
이러한 사용되지 않는 메모리에 대한 회수를 'Garbage Collection'이라고 한다. 자바에서는 프로그램이 사용하는 메모리를 JVM(Java Virtual Machine)이 모두 관리한다.

 

3. OutOfMemory Error 및 해결방법
자바는 객체, 변수등의 생성과 동시에 메모리(Heap)를 차지하게 되고, 문제는 이 객체와 변수를 너무 많이 발생시킴으로 해서 현재 할당된 메모리(Heap)를 초과하게 된다 
그래서 더이상 할당받을 메모리(Heap)가 부족하게 되면 OutOfMemory Error 발생하게 된다. 
OutOfMemory Error 해결방법으로는 
jdk1.4에서 -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintHeapAtGC 옵션을 사용한 GC는 현재상태의 Heap메모리 정보출력 한다. 
GC정보를 통하여 New, Old, Perm 등의 영역중 실제 어느 부분이 부족하여 OutOfMemory가 발생하는지 찾은후 부족한 영역의 충분하 size를조절해 주는 방법으로 해결할 수 있다.

 
4. Heap layout 할당에 영향을 주는 스위치들


5. New Generation 메모리 할당 공식
   Eden = NewSize - ((NewSize/(SurvivorRatio + 2)) * 2)
   From space = (NewSize - Eden)/2
   To space = (NewSize - Eden)/2

 
6. Old Generation 메모리 할당 공식
   Old = Xmx - MaxNewSize
 

7.  JVM 스위치 설정 예제
 1) 현재 
http://www.affis.net 서비스는 2200개의 Jsp파일을 가지고 있고 주로 정적인 페이지들이므로 Jsp 파일 로딩에 필요한 Perm size 위주로 메모리 튜닝을 하였다.
 2) 현재 
http://club.affis.net 서비스는 어플리케이션 동적이페이지들로 작성되어 있고 어플리케이션처리에 필요한  New size 위주로 메모리 튜닝을 하였다.
 

8. 맺음말
OutOfMemory 발생한다면 GC로그를 찍어본다. 
로그를 분석해보면 New(eden, from, to), Old, Perm 등의 영역중에서 GC가 발생해도  메모리 영역이 계속 100%로 할당되는 영역이 보일것이다. 
부족한 영역에 충분한 size 메모리를 할당해 주면 OutOfMemory 해결 된다.
그러나 부족한 영역에 계속해서 메모리 할당을 해주어도 사용률이 100%가 나온다면 프로그램 누수일수 있으니 프로그램을 점검해 봐야 할 것이다.

개발/자바 | Posted by 은우 아빠 2009. 1. 15. 16:25

[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

개발/시스템 | Posted by 은우 아빠 2009. 1. 9. 14:49

netstat의 TCP 연결 상태 의미


netstat의 TCP 연결 상태 의미  

netstat의 State 필드에 표시되는 TCP 상태표시가 갖는 의미를 알아봅시다.
RFC 793 문서에 있는 TCP 기본 연결, 종료 과정을 보면 이해가 더 빠를 거라 생각한다.

-----------------------------------------------------------
# netstat -atn
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address          Foreign Address       State
... 생략 ...
tcp        0      0 0.0.0.0:25             0.0.0.0:*             LISTEN      <-- 포트가 열렸음
tcp        0      0 192.168.123.10:32799   207.46.106.141:1863   ESTABLISHED <-- 서로 연결중
tcp        0      0 192.168.123.10:32794   218.xxx.xx.xx:22      ESTABLISHED
tcp        0      0 192.168.123.10:32802   207.46.108.46:1863    CLOSE_WAIT  <-- 종료 대기중
tcp        0      0 192.168.123.10:33244   211.xxx.xx.x:80       ESTABLISHED
... 생략 ...
-----------------------------------------------------------

1) TCP 연결관련 상태

* RFC 793문서에 나온 기본적인 TCP 연결 과정

      TCP A                                                      TCP B

  1.  CLOSED                                                     LISTEN
  2.  SYN-SENT    --> < SEQ=100>< CTL=SYN>                   --> SYN-RECEIVED
  3.  ESTABLISHED <-- < SEQ=300>< ACK=101>< CTL=SYN,ACK>     <-- SYN-RECEIVED
  4.  ESTABLISHED --> < SEQ=101>< ACK=301>< CTL=ACK>         --> ESTABLISHED
  5.  ESTABLISHED --> < SEQ=101>< ACK=301>< CTL=ACK>< DATA>  --> ESTABLISHED

LISTEN      : 데몬이 요청을 발을 수 있도록 연결 요구를 기다리는 상태
  즉, 포트가 열려있음을 의미. http(80), mail(25), ftp(21), telnet(23) 등
  위에서 포트 25(mail)이 메일을 받을 수 있도록 열려 있는 상태
  윈도우즈에서는 LISTENING으로 표시
SYN_SENT    : 로컬에서 원격으로 연결 요청(SYN 신호를 보냄)을 시도한 상태
SYN_RECV    : 원격으로 부터 연결 요청을 받은 상태
  요청을 받아 SYN+ACK 신호로 응답은 한 상태이지만 ACK는 받지 못했다.
  netstat로 확인할 때 SYN_RECV가 상당히 많다면 TCP SYN 플러딩(Flooding) 공격일
  가능성이 있다.
  윈도우즈와 솔라리스에서는 SYN_RECEIVED으로, FreeBSD는 SYN_RCVD으로 표시
ESTABLISHED : 서로 연결이 되어 있는 상태
  위에서 192.168.123.10의 포트 32794과 218.xxx.xx.xx의 포트 22(ssh)이 서로
  연결되어 있는 상태

2) TCP 종료관련 상태

* 정상적인 연결 종료 과정

      TCP A                                                   TCP B

  1.  ESTABLISHED                                             ESTABLISHED
  2.  (Close)
      FIN-WAIT-1  --> < SEQ=100>< ACK=300>< CTL=FIN,ACK>  --> CLOSE-WAIT
  3.  FIN-WAIT-2  <-- < SEQ=300>< ACK=101>< CTL=ACK>      <-- CLOSE-WAIT
  4.                                                         (Close)
      TIME-WAIT   <-- < SEQ=300>< ACK=101>< CTL=FIN,ACK>  <-- LAST-ACK
  5.  TIME-WAIT   --> < SEQ=101>< ACK=301>< CTL=ACK>      --> CLOSED
  6.  (2 MSL)
      CLOSED                                                    

FIN_WAIT1   : 소켓이 닫히고 연결이 종료되고 있는 상태. 원격의 응답은 받을 수 있다.
  솔라리스에서는 FIN_WAIT_1로 표시
FIN_WAIT2   : 로컬이 원격으로 부터 연결 종료 요구를 기다리는 상태
  솔라리스에서는 FIN_WAIT_2로 표시
CLOSE_WAIT  : 원격의 연결 요청을 받고 연결이 종료되기를 기다리는 상태
  원격으로 부터 FIN+ACK 신호를 받고 ACK 신호를 원격에 보냈다.
TIME_WAIT   : 연결은 종료되었으나 원격의 수신 보장을 위해 기다리고 있는 상태
  이 상태를 특히 자주 보게되는 Apache에서 KeepAlive를 OFF로 해둔 경우,
  Tomcat 서버를 쓰는 경우 등
LAST_ACK    : 연결은 종료되었고 승인을 기다리는 상태
CLOSED      : 완전히 연결이 종료된 상태

※ 위의 FIN_WAIT1, FIN_WAIT2, CLOSE_WAIT 3개 상태는 연결 종료를 위해 서로간에
   신호를 주고받는 과정에 나타나는 상태로 이해하면 된다.
   종료 요청을 한 곳에서는 FIN_WAIT1, FIN_WAIT2, TIME_WAIT 상태가
   종료 요청을 받는 곳에서는 CLOSE_WAIT, LAST_ACK 상태가 표시된다.

3) 기타

CLOSING     : 연결은 종료되었으나 전송도중 데이타가 분실된 상태
UNKNOWN     : 소켓의 상태를 알 수 없음

솔라리스의 netstat 명령에서는 다음 2개의 상태를 더 표시한다.

IDLE        : 소켓이 열렸지만 binding 되지 않은 상태
BOUND       : listen이나 연결을 위한 준비 상태