내가 기고한 어떤 글에 어느 분께서 질문을 올려서 여기에 정리한다.
질문의 골자는 "다른분께서 Perm 영역에서는 GC 가 발생 안한다고 했는데, Perm영역에서도 GC발생한다는 것이 이상하다"는 내용이다. 
나도 내 눈으로 확인하기 전까지는  GC가 발생안한다고 생각했으므로 당연한 질문이라고 생각한다.
지금까지 내가 무슨 이야기하는지 이해가 안되시는 분은
이글 (http://helloworld.naver.com/helloworld/1329) 먼저 읽으시면 조금 이해가 쉬울 것이다. 

다음의 소스를 보자.

public class InternTest {

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

    InternTest test=new InternTest();

    Thread.sleep(10000);   System.out.println("Starting");

    while(true) {

      test.callIntern();Thread.sleep(5000);

      System.out.print(".");

    }

  }

  private void callIntern() {

    for(int loop=0;loop<10000;loop++) {

      String a="1234567890"+System.nanoTime();

      String newString=a.intern();

    }

  }

}

 아주 간단한 소스인데, callIntern() 이라는 메소드를 보면 새로운 String을 계속 만들어 intern() 메소드를 호출하고 있다. 
이 클래스를 컴파일하고 jstat으로 모니터링하면 다음과 같은 결과를 볼 수 있다.
(jstat에 대해서는 "자바 성능을 결정짓는 코딩 습관과 튜닝 이야기"를 참조하거나,
http://helloworld.naver.com/helloworld/6043 를 참고하기 바란다.)

예를 들어 이 프로그램의 프로세스 ID가 4800 일 때 결과는 다음과 같이 출력된다.  

$ ./jstat -gcutil  4800 3s
  S0   S1   E     O    P     YGC  YGCT  FGC FGCT  GCT
  0.00 0.16 10.43 8.79 
98.37 3869 1.247 87  1.815 3.061
  0.02 0.00 52.12 8.77 
45.21 3884 1.250 88  1.840 3.090
  0.00 0.16 83.39 8.77 
98.89 3903 1.257 88  1.840 3.097
  0.00 0.16 27.11 8.78 
15.04 3919 1.262 89  1.857 3.119

 
P라고 표시되어 있는 내용의 값이 계속 변경되는 것을 볼 수 있다.
여기서 P가  Perm 영역의 사용량(%)인데, 보는 것과 같이 그 크기가 지속적으로 바뀌는 것을 볼 수 있다.
그리고 우측에 있는 FGC라는 값도 증가하는 것이 보인다.

자바의 Perm 영역에 클래스와 메소드 정보만 저장되어 있다고 생각하는 것이 일반적이지만,
실제로는 intern된 String 값도 이 영역에 저장된다. 

참고) intern된 String은 뭘까?
String은 기본적으로 equals()메소드로 값을 비교한다. 그렇게 되면 char값들을 비교하기 때문에 성능이 느릴 수 있지만, String 의 실제 값에 대해서 intern() 메소드를 호출하면 해당 값은 equals() 메소드가 아닌 == 으로 비교가 가능하다. 추가로 이  intern()메소드는 native 메소드로 선언되어 있다. 
하지만, 이렇게 String비교를 조금 빠르게 하기 위해서 intern() 메소드를 호출한 후 결과를 비교하는 것은 Perm영역을 마구잡이로 사용하겠다는 의미이기 때문에 "절대" 권장하는 방법은 아니다. 그냥 이런 것이 있구나 정도로 참고하고 있기 바란다. ^^;

추가로,
Perm영역에 어떤 데이터들이 저장되어 있는지 보려면 
jmap -permstat pid
명령어로 확인하면 되며,
그 결과에 가장 첫 출력물을 보면 interned String 크기가 출력된다.


2013.8.5 추가
와 
(의 댓글)에 따르면 JDK 7 이상 부터는 String.intern() 메소드의 호출 결과가 더 이상 Perm 영역에 들어가지 않고 Heap 영역으로 들어가게 되었네요. ^^;


 


Posted by tuning-java
,

top이라는 명령어로 리눅스를 모니터링하다보면
VIRT 와 RES가 있는 것을 볼 수 있다. 


man top 에서 확인해 보니

VIRT  --  Virtual Image (kb)

          The total amount of virtual memory used by the task.  It includes all code, data and shared libraries plus pages that have been swapped out. (Note: you  can define the STATSIZE=1 environment variable and the VIRT will be calculated from the /proc/#/state VmSize field.)

          VIRT = SWAP + RES.


RES  --  Resident size (kb)

          The non-swapped physical memory a task has used.

          RES = CODE + DATA.


요렇게 나온다. 

결론적으로 해당 프로세스에서 물리적인 메모리를 사용하는 크기는 RES 이며,

SWAP 영역에서 사용하는 메모리 + shared + swapped를 합친것이 VIRT 다.


따라서 VIRT 값과 RES 값의 차이가 크다는 이야기는 SWAP 을 쓸 확률이 높다는 의미 인 것으로 보인다. 자바에서는 Shared 메모리의 크기가 그리 크지 않으므로, 만약 VIRT 만 크다면 SWAP 확인해 보고, 애플리케이션에서 도대체 무슨 일이 일어나는지를 잘 째려봐야 할 듯 하다.

어떻게 째려 봐야 할지는 좀 고민 해봐야 할 듯~~~ 

Posted by tuning-java
,
지금까지 알만한 분들에게만 이야기한 지금 집필중인 책의 진척사항을 정리해보고자 한다.

현재 열심히 집필중인 "OO 자바"의 집필 진도율을 오늘 확인해 봤더니 90%다.
1월 중순이니 2월말까지 본문에 대한 집필은 끝낼 수 있을 것 같다. ㅎㅎㅎ

3월부터 두달간은 베타 리더들을 선정하여 베타리뷰 진행하고,
그 사이에 부록을 정리할 예정이다. (부록을 열심히 보는 사람은 그리 많지 않으므로. ㅎㅎ)
4월말, 5월초에 출판사에 넘기면 7월초에 나올 듯 하다.

이 글을 읽는 여러분들이 지금까지 봐 왔던 자바책과는 완전히 다른,
현업에서 꼭 필요한 주옥같은(?) 내용들만 포함되어 있는 책이라 기대해도 좋을 것이다.

마음 같아서는 모두 대박나라는 뜻에서 "대박 자바"라고 하고 싶지만,
이 책의 이름은 벌써 정해 졌다.
(7월달이면 모두 알게 되겠지만... ) 

이 책 출간이 완전히 끝나면,
잠시 쉬었다(?)가
나의 첫 책 리뉴얼에 들어갈 것이다.  
("자바 성능을 결정짓는 코딩 습관과 튜닝 이야기"의 2nd edition ... ㅎㅎㅎㅎㅎ )  
Posted by tuning-java
,
subversion이라는 소스 저장소를 사용할 때 이클립스와 연동하려면,
suvversive 나 subclipse 중 하나를 선택해서 일반적으로 사용한다.

이번에는 subclipse를 설치했고,
방법은 다음과 같다.

1) Java HL 설치
subclipse가 c 기반으로 개발되어 있으므로, 이클립스와 통신하기 위해서는 자바 기반으로 되어 있는 Java HL 이라는 것을 설치해야만 한다. 여러가지 방법이 있겠지만, 맥에서는 그냥 맥포트를 사용하면 된다.
$ su
(root 권한으로 로긴)
$ port install subversion-javahlbindings
(Java HL 설치... 별걸 다 설치한다. ant, junit 등을 최신버전으로 ...)
마지막에 나오는 Java HL의 버전을 꼭 확인한다. 


2) subclipse 설치
http://subclipse.tigris.org/ 
에서 Java HL 버전에 맞는 subclipse 업데이트 URL을 확인한 후 이클립스에서 설치 작업 진행.
그냥 모두 선택하고 설치하면 됨.
(뭐 자세한 내용은 다 알테니 패스)
 
이렇게 설치 해서
이클립스 -->  환경 설정 --> Team --> SVN 으로 이동했을 때, 중간에 있는 Java HL 드롭다운 박스에서 Java HL이 잘 먹혀 있다는 메시지가 나오면 끝.
(버전이 안맞으면 다시 설치해야함. 너무 앞서가서 subclipse를 최신 버전으로 깔아버리면 안됨 - -) 
Posted by tuning-java
,