2018. 10. 25. 11:35

1. 조사배경

  특정 구간에 로그를 찍지 않아서 현재 프로그램이 동작하고 있는지 없는지 알수가 없다



2. 알고 싶은것

  해당 프로세스의 특정 변수를 모니터링 해서 그 값이 변하는지 확인 !! 즉 특정 변수의 값을 보고 싶다.



3. 도구

  jmap ==> java dump 생성

  jhat ==> dump 를 분석하여 Web 서버를 띄워준다.



4. 분석 방법

   1) 분석을 하려는 PID를 가져온다.

       ex) jps를 하여 PID를 가져옴   


   2) java heap 메모리 덤프를 만든다.

       ex) jmap -dump:format=b,file=heap.hprof 8680  ==> 8680 프로세스를 binary 형식의 파일은 heap.hprof로 해서 덤프를 생성한다.


   3) jhat을 사용하여 분석한다. 

       ex) jhap heap.hprof  [enter]  ==> 자동으로 웹서버를 띄워준다.


Reading from heap.hprof...

Dump file created Thu Oct 25 10:58:47 KST 2018

Snapshot read, resolving...

Resolving 788140 objects...

Chasing references, expect 157 dots.............................................................................................................................................................

Eliminating duplicate references.............................................................................................................................................................

Snapshot resolved.

Started HTTP server on port 7000

Server is ready.


    4) 이제 해당 서버에 웹 브라우져로 접속만 하면 된다.

        ex) chrom 으로 http://{웹서버IP}:7000 하여 접속한다.

     


   5) 예제

     PITargetDBManager>m_arrScanThread>currentTable >inspectedRow 의 값을 보고 싶을때

    

   1) 웹에 접속하고

   2) 첫 화면에서  PITargetDBManager를 찾고 링크 들어간다. (처음 보이는 것)

   3) 실행 인스턴스를 찾아서 링크 들어간다. (보통 com.somansa.manager.PITargetDBManager@0xXXXXXX 되어 있다.)

    3) m_arrScanThread로 검색하여 링크 들어간다.

    4) 배열 이므로 아무 인스턴스 링크를  들어간다.           ( com.somansa.manager.DBDiscoverScanThread@0xXXXXXXXXXX)

    4) currentTable  찾고 링크 들어간다.

   5) inspectedRow를 찾고 값을 확인한다.

Posted by citrine
2018. 10. 22. 17:08

1. 조사배경

  - 묵혀둔 MSSql이 있었다. (한 2년 접속 안함)

  - 접속하니 enableSSL xxx 하면서 ssl 로그가 뜬다.

  - 다음과 같은 로그를 남기고 접속이 안된다.


   드라이버가 SSL(Secure Sockets Layer) 암호화를 사용하여 SQL Sever로 보안 연결을 설정할 수 없습니다. 오류: "java.security.cert.CertificateException: Certificates do not conform to algorithm constraints". ClientConnectionId:60f65f8c-e751-4cff-90d9-69928ae25ef8



2. 원인

  java 가 Update되면서 일부 key를 사용못하게 함

  즉 client 는 최신

     server는 Old ==> 


  즉 서버에서 키 문제가 존재하는 것으로 handshake 할려고 하는데.. 그게 문제가 되는가 부다.



3. 해결

client의   JRE_HOME/lib/security/java.security 파일을 열어서


  다음 속성

 jdk.certpath.disabledAlgorithms

 jdk.tls.disabledAlgorithms


을 주석 처리함.. 즉 알고리즘 다 사용하게 함...

==>  정확히 처리할려면 서버도 알고리즘을 맞추어 주어야 되는데 mssql ssl 알고리즘 설정을 어디서 하는지 모르겠다.



# 참고

1. 에러 원문

 com.microsoft.sqlserver.jdbc.SQLServerException: 드라이버가 SSL(Secure Sockets Layer) 암호화를 사용하여 SQL Sever로 보안 연결을 설정할 수 없습니다. 오류: "java.security.cert.CertificateException: Certificates do not conform to algorithm constraints". ClientConnectionId:60f65f8c-e751-4cff-90d9-69928ae25ef8

at com.microsoft.sqlserver.jdbc.SQLServerConnection.terminate(SQLServerConnection.java:1668)

at com.microsoft.sqlserver.jdbc.TDSChannel.enableSSL(IOBuffer.java:1668)

at com.microsoft.sqlserver.jdbc.SQLServerConnection.connectHelper(SQLServerConnection.java:1324)

at com.microsoft.sqlserver.jdbc.SQLServerConnection.login(SQLServerConnection.java:992)

at com.microsoft.sqlserver.jdbc.SQLServerConnection.connect(SQLServerConnection.java:828)

at com.microsoft.sqlserver.jdbc.SQLServerDriver.connect(SQLServerDriver.java:1012)

at java.sql.DriverManager.getConnection(DriverManager.java:664)

at java.sql.DriverManager.getConnection(DriverManager.java:208)

at com.somansa.db.connection.DBConnection.getConnection(DBConnection.java:238)

at com.somansa.db.connection.PIScanDBConnection.InspectDBStructure(PIScanDBConnection.java:332)

at com.somansa.manager.PITargetDBManager.inspectDBStructure(PITargetDBManager.java:588)

at com.somansa.manager.PIGetDBInfoManager.getDBinfoProcess(PIGetDBInfoManager.java:41)

at com.somansa.manager.PIGetDBInfoManager.run(PIGetDBInfoManager.java:133)

at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)

at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)

at java.lang.Thread.run(Thread.java:748)

Caused by: javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: Certificates do not conform to algorithm constraints

at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)

at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1946)

at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:316)

at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:310)

at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1639)

at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:223)

at sun.security.ssl.Handshaker.processLoop(Handshaker.java:1037)

at sun.security.ssl.Handshaker.process_record(Handshaker.java:965)

at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1064)

at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1367)

at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1395)

at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1379)

at com.microsoft.sqlserver.jdbc.TDSChannel.enableSSL(IOBuffer.java:1618)

... 14 more

Caused by: java.security.cert.CertificateException: Certificates do not conform to algorithm constraints

at sun.security.ssl.AbstractTrustManagerWrapper.checkAlgorithmConstraints(SSLContextImpl.java:1127)

at sun.security.ssl.AbstractTrustManagerWrapper.checkAdditionalTrust(SSLContextImpl.java:1051)

at sun.security.ssl.AbstractTrustManagerWrapper.checkServerTrusted(SSLContextImpl.java:993)

at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1621)

... 22 more

Caused by: java.security.cert.CertPathValidatorException: Algorithm constraints check failed on keysize limits. RSA 512bit key used with certificate: CN=RIKKY-PC-X64.  Usage was tls server

at sun.security.util.DisabledAlgorithmConstraints$KeySizeConstraint.permits(DisabledAlgorithmConstraints.java:817)

at sun.security.util.DisabledAlgorithmConstraints$Constraints.permits(DisabledAlgorithmConstraints.java:419)

at sun.security.util.DisabledAlgorithmConstraints.permits(DisabledAlgorithmConstraints.java:167)

at sun.security.provider.certpath.AlgorithmChecker.check(AlgorithmChecker.java:332)

at sun.security.ssl.AbstractTrustManagerWrapper.checkAlgorithmConstraints(SSLContextImpl.java:1123)

... 25 more


2. 참고 사이트

https://stackoverflow.com/questions/21218217/ssl-handshake-exception-algorithm-constraints-check-failed-md5withrsa

Posted by citrine
2018. 9. 10. 14:43

1. 조사 배경

  - 회의 Class가 순환 참조되는 구조임 그래서 Gson을 못 씀


2. 해결

  순환 참조되는 필드에 "transient" 한정자를 준다.


3. 예제

  class BagOfPrimitives {

     private int value1 = 1;
     private String value2 = "abc";
     private transient int value3 = 3;
     BagOfPrimitives() {
      // no-args constructor
  }
}

  1) Class에 순환 참조되는 필드 "value3"가 존재한다면 transient 를 넣는다.



4. 참조 

https://sites.google.com/site/gson/gson-user-guide#TOC-Finer-Points-with-Objects

Posted by citrine
2017. 9. 13. 13:37

ResourceBundle을 사용할 때, 가끔 아래와 같은 에러가 출력된다.

Err: java.util.MissingResourceException: Can't find bundle for base name ~~.~~ locale ko_KR 


대개 실행 시에 ClassLoader가 폴더 밖으로 접근할 수 없어서 권한 문제 때문에 에러가 나는 것이라고 한다.


해결 방법은 간단하다.

아래와 같이 프로젝트 옵션에서 '클래스폴더로 /locale 폴더를 추가'하면 끝.




출처: http://strongslaves.tistory.com/20 [튼튼한노예들]

Posted by citrine
2017. 4. 28. 15:40

Java Press (http://www.gihyo.co.jp/magazines/javapress) 라는 일본의   
Java전문 서적(2003년 2월판)에서 발췌한 Java performance tips입니다.   

그중 Java 일반적사항에 관련하여 7개, String 관련2개, Collection관련 8개,   
IO관련2개등 총 4개 분야 19여개의 Tips에 대해 제가 나름대로 번역해본 자료입니다.   

출처 : javaservice.net 김선필(piper2)님의 글입니다. 

Java performance tips 

Java Press (http://www.gihyo.co.jp/magazines/javapress) 라는 일본의 Java전문 서적(2003년 2월판)에서 발췌한 Java performance tips입니다. 

그중 Java 일반적사항에 관련하여 7개, String 관련2개, Collection관련 8개, IO관련2개, 
등 총 4개 분야 19여개의 Tips에 대해 설명하겠습니다. 

1. 일반적사항 관련 Tips 

    ① 쓸데없이 Cast를 남발하면 바람직하지 않음. 
     
     Loop구조에서 쓸데없이 cast를 남발하면 performance를 현저히 저하시킵니다. 

      예) 쓸데없이 cast를 남발한 바람직하지 않은 코드예 

      for(int i=0; i<list.size(); i++) 
      { 
        if ( ((String)list.get(i)).indexOf('a') ! =-1)  { 
        } else if(((String)list.get(i)).indexOf('b') ! =-1)  { 
        } else if(((String)list.get(i)).indexOf('c') ! =-1)  { 
        } else if(((String)list.get(i)).indexOf('d') ! =-1)  { 
        } ... 
      } 

      예) 쓸데없는 cast를 제거한 좋은 코드예 

      for (int i=0; i<list.size(); i++) 
      { 
        String value = (String)list.get(i); 
        if(value.indexOf('a') ! = -1) { 
        } else if ((value.indexOf('b') != -1){ 
        } else if ((value.indexOf('c') != -1){ 
        } else if ((value.indexOf('d') != -1){ 
        } ... 
      } 

    ② 쓸데없이 동기화를 행하면 바람직하지 않음 
     
        同期化(Synchronized)은 높은 cost입니다. 필요가 없을 시에는 사용하지 마십시요. 


    ③ 쓸데없는 인스턴스생성은 바람직하지 않음 

        인스턴스수가 많지 않은 경우에는 별 문제가 되지 않겠지만, 많은 인스턴스를 생성 
하는 경우에는 performance를 현저히 저하 시키므로 주의하십시요. 

        예) String 인스턴스를 2번생성한 바람직 하지 않은 코드예 

          String value = new String("문자열"); 

        예) 개량 후 코드예 

          String value = "문자열"; 


    ④ 필요이상으로 Wrapper클래스를 사용하면 바람직하지 않음 

        Wrapper클래스(Integer, Boolean 등)을 클래스멤버로 사용하는 경우 인스턴스생성 
이 필요하게 되므로, 기본적으로 Primitive형을 사용하는 편이 performance를 높 
입니다. 

        예) Wrapper클래스를 사용한 코드예 

        public class Person { 

          private Integer id; 
          private Boolean isValid; 
        }; 

        예) primitive형으로 치환한 코드예 

        public class Person { 

          private int id; 
          private boolean isValid; 
        };   

        또한 Wrapper클래스에는 없지만 java.math.BigDecimal 클래스는 Double 클래스 
보다 정확한 부동소수연산이 가능하지만 performance를 저하시키므로 유의바랍니 
다. 

    ⑤ primitive형의 default값을 이용 

int형 boolean형등의 primitive형은 선언시 default값이 초기화 됩니다. 이것을 이용하면 초기화처리를 생략할 수 있습니다. 덧붙여 말하면 int형은 0, float은 0.0, boolean형은 false로 선언시에 초기화 됩니다. 

        예) primitive형의 초기화처리를 행한 코드예 

        public class Person { 

          private int id; 
          private boolean isValid; 

          public Person() { 

            id = 0; 
            isValid = false; 
          } 
        } 

        예) primitive형의 default값을 이용한 코드예 

        public class Person { 

            private int id; 
            private boolean isValid; 

            public Person() { 

            } 
          } 


    ⑥ 문자열을 숫자형으로 변환하는 방법 

        문자열을 숫자형으로 변환시에 각 Wrapper클래스(Integer,Double 등)의 static 메 
소드인 parseXXX()를 이용합니다. 
        valueOf()를 경유해서 XXXValue()를 실행하면 한번의 인스턴스를 생성하게 되어 
불필요한 cost를 들게 합니다. 

        예) valueOf()를 이용하여 문자열을 숫자형으로 변환한 코드예 

          double doubleValue = Double.valueOf("1234.56").doubleValue(); 
          int intValue = Integer.valueOf("123456").intValue(); 

        예) 개량한 코드예 

          double doubleValue = Double.parseDouble("1234.56"); 
          int intValue = Integer.parseInt("123456"); 


    ⑦ 필요이상으로 System.gc()를 사용하면 바람직하지 않음 
       
        필요이상으로 System.gc()를 이용하면 프로그램실행 performance가 저하됩니다. 



   
  2. String 관련 Tips 

    ① 문자열 연결방법 
        +연산자를 이용하여 문자열을 연결하게 되면 심하게 performance가 저하됩니다. 
        StringBuffer클래스를 사용하면 performance가 향상됩니다. 
     
        예) + 연산자에 의한 문자열연결 코드예 

          String result = "";           
for (int i=0; i<loopNum; i++ )  { 
result + =i; 
          } 
        예) StringBuffer클래스에 의한 문자열연결 코드예 

          StringBuffer buf = new StringBuffer(); 
          for(int i=0; i<loopNum; i++) { 
            buf.append(i); 
          } 
          String result = buf.toString(); 

        더욱이, 연결후의 문자열의 길이를 알고 있을 경우,  StringBuffer클래스 생성시에 
적당한 초기값을 주면 더욱더 performance가 향상됩니다. 
        StringBuffer클래스는 용량이 부족하게 되면 내부적으로 버퍼사이즈가 자동으로 변 
경되나 연결후의 사이즈를  알고 있는 경우에는 초기값으로 사이즈를 주면 그러한 
처리과정을 생략할 수 있습니다. 
   
      예) StringBuffer buf = new StringBuffer(length); 

       표) 문자열연결에 관한 performance 측정 
                                                         
        연결수: 1000        연결수 : 500         
+연산자        250(ms)        7500(ms)         
StringBuffer        15(ms)        20(ms)         
StringBuffer(초기값有)        2(ms)        10(ms)         
        CPU : Pentium 300MHz/ Memory :128M / OS : Linux/ J2SE:1.3.1 
                                                 
    ② StringTokenizer클래스 
       
문자열을 자를 때,StringTokenizer클래스를 이용하는 것이 편하기는 하지만 문자열 
이 고정되어 있는 경우에는 독자적인 Tokenizer를 사용하는것이 효율적입니다. 

StringTokenizer클래스가 token을 반복할때, 매번 자를문자가 변경되어 있는지를 
체크하기 때문입니다. 

       예) StringTokenizer클래스를 취하는 코드예 

         String word = "aaa,bbb,ccc,ddd,eee,fff"; 

         StringTokenizer token = new StringTokenizer(word,","); 

         List list = new ArrayList(); 
         
         while(token.hasMoreTokens()) { 
           list.add(token.nextToken()); 
         } 
         
       예) 자를문자를 ‘,’로 고정한후 token을 추출한 코드예 

          String word = "aaa,bbb,ccc,ddd,eee,fff"; 
           
          List list = new ArrayList(); 

          int now=0; 
          int next=0; 

          while ( (next = word.indexOf(",",now)) > 0 ) 
          { 
            list.add(word.substring(now,next)); 
            now = next + 1; 
          } 
         

        또한 StringTokenizer클래스에는 hasMoreElements()와 hasMoreTokens() 두개의 
메소드가 있는데,  hasMoreElements()가 내부적으로 hasMoreTokens()를 호출하 
므로 통상적으로 hasMoreTokens()를 이용 하도록 합니다. 

        참고) J2SE 1.4부터 새로운 메소드가 추가된것이 있는데, SringTokenizer 클래스의 
token 추출과 같은 기능의 메소드로 java.lang.String 클래스의 split()메소드를 소 
개합니다. 

          String word = "aaa,bbb,ccc,ddd,eee,fff"; 
          String [] result = word.split(","); 
   
3. Collection관련 Tips 
     
    ① 배열의 이용 
         
데이타의 개수나 사이즈가 변동하는 경우에만 Collection계통의 클라스를 사용하며, 
그외에는 배열을 사용합니다. 
       
    ② J2SE1.2이상에서의 Collection이용 

JDK1.1까지는 Vector클래스나 Hashtable클래스가 편리했으나, 이러한 클래스는 메소드가 동기화(synchronized) 
되어 있습니다. 따라서 동기화가 필요없는 경우에는 비효율적입니다. 
J2SE1.2이상에서는 메소드가 동기화되어있지 않은 ArrayList클라스나 HashMap클 
래스를 이용합니다. 
       Vector클래스는 ArrayList로 Hashtable은 HashMap클래스로 바꿔이용합니다. 

        예) 구 Collection클래스 이용예 
           
           Vector vector = new Vector(); 
           Hashtable table = new Hashtable(); 

        예) J2SE1.2이상 Collection클래스 이용예 
           
           List list = new ArrayList(); 
           Map  map  = new HashMap(); 

        또한, J2SE1.2이상에서 Collection의 동기화가 필요한 경우에는 

           List list = Collection.synchronizedList(new ArrayList(..)); 
         
        위와 같이 사용합니다.             
     
    ③ Collection size 초기화 

Collection을 default 사이즈로 만들면, 필요시 자동적으로 사이즈가 확장되나 명확히 예측이 가능한 경우에는 사이즈를 초기화 하는 편이 훨씬 효율적입니다. 

        예) 사이즈를 지정하지 않고 Collection을 생성한 코드예 

          List list = new ArrayList(); 
          HashMap map = new HashMap(); 

        예) 사이즈를 지정한 Collection 생성 코드예 
             
          List list = new ArrayList(num); 
          HashMap map = new HashMap(num); 


    ④ Iterator클래스보다 빠른 요소검사 

       Collection 사이즈를 명확히 알 경우에는 Iterator클래스의 next()와 비교하여, 
       Iterator클래스의 hasNext()에 의한 요소종료 체크가 필요없으며 내부처리가 간단한 
       List클래스의 get()메소드를 추천합니다. 

       예) Iterator클래스의  next()에 의한 요소조사 

         Iterator iterator = array.iterator(); 
         while (iterator.hasNext()) 
         { 
           Object object = iterator.next(); 
         } 

       예) List클래스의 get()에 의한 요소조사 

          int size =array.size(); 
          for (int i=0; i<size ; i++) 
          { 
            Object object = array.get(i); 
          } 
           
    ⑤ 요소삽입/삭제시 주의점 

        List도중에 요소를 추가/삭제할 경우에 내부적으로 배열의 copy가 행해집니다. 
따라서 요소의 수가 많으면 많을 수록 copy하는 요소수도 많아져 결과적 
으로 performance의 저하를 초래합니다. 
내부적처리로써 [ (전체사이즈) - (삽입/삭제대상요소의 index)] 만큼의 요소가 copy되므로 아래의 예를 참조바랍니다. 

        예) List의 맨앞에 요소를 추가/삭제하는 경우 --  속도가 느림. 

         list.add(0, new Object()); 
         list.remove(0); 

        예) List의 맨 뒤에 요소를 추가/삭제하는 경우 -- 속도가 빠름. 

         list.add(new Object()); 
         list.remove(list.size() - 1); 


    ⑥ List요소 전체삭제 

List요소를 전체삭제 할때, 통상 쓰는 clear()을 이용하지말고, 새롭게 List를 생성(초기화)하는 편이 효율적입니다. 왜냐하면, clear()는 내부적으로 보유하고 있는 배열의 전체요소에 null을 셋팅함으로써 전체삭제를 실현하기 때문입니다. 

        예) clear()에 의한 요소 전체삭제 

          List list = new ArrayList(); 
           
          for(int i=0; i< num; i++) { 
            list.add(new Integer(i)); 
          } 

          list.clear(); 

        예) List재작성에 의한 요소 전체삭제 

          List list = new ArrayList(); 

          for(int i=0; i< num; i++) { 
            list.add(new Integer(i)); 
          } 

          list = new ArrayList(); 

    ⑦ 배열요소 copy방법 
     
루프를 돌며 배열요소를 하나씩 copy할 경우에는 System.arraycopy(Object src,int srcPos,Object dest,int destPos,int length)를 이용합니다. 
        메소드의 인자는 아래와 같습니다. 

          src - the source array. 
          srcPos - starting position in the source array. 
          dest - the destination array. 
          destPos - starting position in the destination data. 
          length - the number of array elements to be copied. 
         
        예) 루프를 돌며 배열소소를 copy하는 예 

           int[] buf = new int[num]; 
           int[] copy = new int[num]; 

           for (int i=0; i<num; i++) 
           { 
              copy[i] = buf[i]; 
           } 
         
        예) System.arraycopy()에 의한 신속한 copy 예 

           int[] buf = new int[num]; 
           int[] copy = new int[num]; 

           System.arraycopy(buf,0, copy,0, num); 

     ⑧ List에 보존되어 있는 object 요소를 배열에 넣는 방법 

List클래스의 toArray()를 이용하여 List에 보존되어 있는 Object요소를 배열에 넣습니다. 

          예) 루프에 의한 object요소 copy 예 
               
            int size = list.size(); 
            Integer[] result = new Integer[size]; 

            for (int i=0; i<size; i++) 
            { 
              result[i] = (Integer) list.get(i); 
            } 

          예) toArray()에 의한 신속한 copy 

            int size = list.size(); 
            Integer[] result = new Integer[size]; 

            list.toArray(result); 





4. IO관련 Tips 

     ① 통상적으로 Stream계의 클래스를 사용함 

        java.io패키지에서 문자데이터 입출력시에는 Reader/Writer 클래스를 
        바이트단위 데이터 입출력시에는 InputStream/OutputStream 을 이용합니다. 
        다만, 아스키캐릭터의 경우에는 1문자가 1바이트이므로 
InputStream/OutputStream 클래스를 이용할 수 있습니다. 
         
        약 100K 정도의 영문자로 이루어져 있는 텍스트파일을 가지고 예를 들겠습니다. 

        예) Reader계 클래스을 이용한 파일 입출력 예 

            FileReader in = new FileReader("test.txt"); 
            int buf; 

            while ( buf = in.read() != -1) 
            { 
              ....... 
            } 
            in.close(); 

        예) InputStream계 클래스를 이용한 파일 입출력 예 

            FileInputStream in = new FileInputStream("test.txt"); 
            int buf; 

            while ( buf = in.read() != -1) 
            { 
              ....... 
            } 

            in.close(); 

          위의 2가지 예를 비교한 performance 비교표는 아래와 같습니다. 
               
사용클래스        처리시간(ms)         
FileReader        18000         
FileInputStream        800         
CPU : Pentium 300MHz/ Memory :128M / OS : Linux/ J2SE:1.3.1 

InputStream계 클래스를 이용한 파일 입출력이 월등히 빠른 처리속도를 보임을 알 수 있습니다. 
             
     ② Buffering을 이용 

        예) Buffering을 한 Reader계 클래스을 이용한 파일 입출력 예 

            FileReader in = new FileReader("test.txt"); 
            BufferedReader bin = new BufferedReader(in); 
            int buf; 

            while ( buf = bin.read() != -1) 
            { 
              ....... 
            } 

            bin.close(); 

        예) Buffering을 한 InputStream계 클래스를 이용한 파일 입출력 예 

            FileInputStream in = new FileInputStream("test.txt"); 
            BufferedInputStream bin = new BufferedInputStream(in); 
            int buf; 

            while ( buf = bin.read() != -1) 
            { 
              ....... 
            } 
            bin.close(); 

위의 2가지 예를 비교한 performance 비교표는 아래와 같습니다. 

사용클래스        처리시간(ms)         
BufferedReader        150         
BufferedInutStream        80         
CPU : Pentium 300MHz/ Memory :128M / OS : Linux/ J2SE:1.3.1 


- the end-



출처: http://pracon.tistory.com/107 [푸른너구리의 보금자리]

Posted by citrine
2016. 10. 21. 09:51

1. 용도 : 메모리 Leak이나 OOME 발생시 분석 용도


2. 절차

  1) 해당 PID를 얻어온다 

      jps


  2) 메모리 덤프를 발생시킨다.

jmap -dump:file=a.dump ${PID}

# jmap을 통해 어느정도 직접 분석도 가능하다. 사이트에서는 jmap, jhat을 정확히 알고 사용해야 겠다.


  3) Memory Analyzer를 이용하여 분석한다.(http://www.eclipse.org/mat/)

Posted by citrine
2016. 10. 21. 09:40

1. 용도 : OOME(Out of Memory Error) 발생시 dump를 발생하여 추후 분석 용도


2. 코드


/* *********************************************************************************************************** */


Programmatically dumping heap from Java applications

In the troubleshooting BOF, we demonstrated how to use the jmap -dump option to dump heap dump of a running application and showed how to browse/analyze the resulting binary heap dump using the jhat tool.

One of the questions was how to programmatically dump the heap from applications. For example, you may want to dump multiple heap snapshots from your application at various points in time and analyze those off line using jhat. Yes, you can dump heap from your application -- but you have to do a bit of programming as shown below:


import javax.management.MBeanServer;
import java.lang.management.ManagementFactory;
import com.sun.management.HotSpotDiagnosticMXBean;

public class HeapDumper {
    // This is the name of the HotSpot Diagnostic MBean
    private static final String HOTSPOT_BEAN_NAME =
         "com.sun.management:type=HotSpotDiagnostic";

    // field to store the hotspot diagnostic MBean 
    private static volatile HotSpotDiagnosticMXBean hotspotMBean;

    /\*\*
     \* Call this method from your application whenever you 
     \* want to dump the heap snapshot into a file.
     \*
     \* @param fileName name of the heap dump file
     \* @param live flag that tells whether to dump
     \*             only the live objects
     \*/
    static void dumpHeap(String fileName, boolean live) {
        // initialize hotspot diagnostic MBean
        initHotspotMBean();
        try {
            hotspotMBean.dumpHeap(fileName, live);
        } catch (RuntimeException re) {
            throw re;
        } catch (Exception exp) {
            throw new RuntimeException(exp);
        }
    }

    // initialize the hotspot diagnostic MBean field
    private static void initHotspotMBean() {
        if (hotspotMBean == null) {
            synchronized (HeapDumper.class) {
                if (hotspotMBean == null) {
                    hotspotMBean = getHotspotMBean();
                }
            }
        }
    }

    // get the hotspot diagnostic MBean from the
    // platform MBean server
    private static HotSpotDiagnosticMXBean getHotspotMBean() {
        try {
            MBeanServer server = ManagementFactory.getPlatformMBeanServer();
            HotSpotDiagnosticMXBean bean = 
                ManagementFactory.newPlatformMXBeanProxy(server,
                HOTSPOT_BEAN_NAME, HotSpotDiagnosticMXBean.class);
            return bean;
        } catch (RuntimeException re) {
            throw re;
        } catch (Exception exp) {
            throw new RuntimeException(exp);
        }
    }

    public static void main(String[] args) {
        // default heap dump file name
        String fileName = "heap.bin";
        // by default dump only the live objects
        boolean live = true;

        // simple command line options
        switch (args.length) {
            case 2:
                live = args[1].equals("true");
            case 1:
                fileName = args[0];
        }

        // dump the heap
        dumpHeap(fileName, live);
    }
}

By including the above class in your application, you can call HeapDumper.dumpHeap whenever you want to dump the heap as shown in the sample main.

Important note: while you can dump multiple heap snapshots from your application, you can not correlate the objects from multiple dumps. jmap tool uses object addresses as object identifiers - which vary between garbage collections [recall that GC may move objects which changes the object addresses]. But, you can correlate by aggregate stat such as histogram etc.


/* *********************************************************************************************************** */




# 참고

https://webcache.googleusercontent.com/search?q=cache:hdydNmOObc0J:https://blogs.oracle.com/sundararajan/entry/programmatically_dumping_heap_from_java+&cd=1&hl=ko&ct=clnk&gl=kr


Posted by citrine