2010-07-01 3 views
3

나는 직렬화하고자하는 매우 큰 객체를 가지고있다. 직렬화 과정에서 130MB의 힙을 weblogic.utils.io.UnsyncByteArrayOutputStream으로 사용하게됩니다. BufferedOutputStream을 사용하여 디스크에 데이터를 쓰는 속도를 높이고이 개체가 메모리에 보관되는 시간을 줄입니다.자바 직렬화 중에 객체를 버퍼링 할 수 있습니까?

버퍼를 사용하여 메모리에있는 개체의 크기를 줄일 수 있습니까? 한 번에 x 바이트를 직렬화하고 이러한 바이트를 디스크에 쓰는 방법이 있으면 좋을 것입니다.

샘플 코드는 어떤 용도로든 사용 가능합니다. 생각하지는 않지만 계속 진행할 것은별로 없습니다. 직렬화 될 객체의 전체 메모리 내 복사본이 필요하다면 (따라서 직렬화 버퍼의 개념이 없다면) 나는 막혔다 고 생각합니다.

ObjectOutputStream tmpSerFileObjectStream = null; 
    OutputStream tmpSerFileStream = null; 
    BufferedOutputStream bufferedStream = null; 
    try { 

     tmpSerFileStream = new FileOutputStream(tmpSerFile); 
     bufferedStream = new BufferedOutputStream(tmpSerFileStream); 

     tmpSerFileObjectStream = new ObjectOutputStream(bufferedStream); 
     tmpSerFileObjectStream.writeObject(siteGroup); 
     tmpSerFileObjectStream.flush(); 

    } catch (InvalidClassException invalidClassEx) { 
     throw new SiteGroupRepositoryException(
       "Problem encountered with class being serialised", invalidClassEx); 
    } catch (NotSerializableException notSerializableEx) { 
     throw new SiteGroupRepositoryException(
       "Object to be serialized does not implement " + Serializable.class, 
       notSerializableEx); 
    } catch (IOException ioEx) { 
     throw new SiteGroupRepositoryException(
       "Problem encountered while writing ser file", ioEx); 
    } catch (Exception ex) { 
     throw new SiteGroupRepositoryException(
       "Unexpected exception encountered while writing ser file", ex); 
    } finally { 
     if (tmpSerFileObjectStream != null) { 
      try { 
       tmpSerFileObjectStream.close(); 
       if(null!=tmpSerFileStream)tmpSerFileStream.close(); 
       if(null!=bufferedStream)bufferedStream.close(); 
      } catch (IOException ioEx) { 
       logger.warn("Exception caught on trying to close ser file stream", ioEx); 
      } 
     } 
    } 
+0

직렬화 논리의 몇 가지 예제 코드를 게시 할 수 있습니까? 뭔가가 여기에 추가되지 않습니다 - 그 weblogic 클래스는 어디서 왔습니까? –

답변

0

저장하려는 "siteGroup"개체 란 무엇입니까? 하나의 객체가 크기가 130MB 인 것은 아니기 때문에 목록/배열 /지도/그 밖의 것이 무엇이든 않는 한 그렇게 부탁합니다. 그렇다면 데이터를 데이터베이스에 저장하는 것이 답이 될 것입니다.

개체에 몬스터 컬렉션이 없으면 개체 트리에 bagillion 개체에 대한 참조가 포함되어있을 가능성이 높습니다. 물론 직렬화는 전체 복사본을 만듭니다 (이 사실을 구현하기위한 바로 가기로 사용됨). clone()은 많은 시간을 필요로합니다.) 그래서 모든 것이 하향식으로 한 번에 모두 카탈로그 화됩니다.

이것이 문제라면 솔루션은 각 객체가 상향식으로, 여러 파일로 직렬화되고 각 객체가 전체 객체 대신 다른 객체로 유지되는 자체 직렬화 체계를 구현하는 것입니다. 맡은 일. 이렇게하면 개별 개체를 개별적으로 작성할 수 있습니다. 원하는 효과를 얻을 수 있습니다. 즉, 데이터를 청크로 작성하여 메모리 사용 공간을 줄입니다.

그러나 clone() 메소드를 구현하는 것과 같이 사용자 고유의 직렬화를 구현하는 것이 쉽지는 않습니다. 비용/이점입니다.

+0

실제로 데이터베이스에 유지되는 엄청난 수의 개체 맵을 포함합니다. 직렬화는 데이터베이스에서 맵을 빌드하는 데 몇 분이 걸리지 않고 디스크로부터 1 분 이내에 시작하기 때문에 시작 속도에 불과합니다. –

+0

아. 실제로 일을 더 쉽게 만들 수 있습니다 ...지도를 통해 모든 개체를 개별적으로 직렬화 한 다음지도를 지우고 주 siteGroup 개체를 serialize 할 수 있습니까? 시작할 때, 프로세스를 되돌릴 수 있습니다 :지도를 작성한 다음 객체에 넣으십시오. 최대 힙 크기를 상당히 줄일 수 있습니다. –

0

이유는 unsync 바이트 배열 출력 스트림과 같은 모든 바이트를 차지합니까?

기본 직렬화가 작동하는 방식이 아닙니다. 특정 코드가 있어야만 그렇게 할 수 있습니다. 해결책 :하지 마십시오.

+0

weblogic.utils.io.UnsyncByteArrayOutputStream은 힙 덤프에 표시됩니다. 여기에서 그 정보를 얻었습니다. 이 루틴은 간헐적 인 메모리 부족 오류를 일으키므로 문제가됩니다. Weblogic이 직렬화를 처리하는 방법에 대해 할 수있는 일이 많지 않다고 생각합니다. –

+0

@MarkChorley 질문에 힙 덤프가 없습니다. 중요한 정보를 생략 한 경우에는하지 마십시오. – EJP

0

당신이 사용하고있는 런타임이 객체 직렬화를 덜 이상하게 구현 한 것처럼 들리는 것 같습니다.

꽤 오래되었지만 비슷한 불만 사항이 여기에 언급되어 있습니다. http://objectmix.com/weblogic/523772-outofmemoryerror-adapter.html

더 새로운 버전의 weblogic을 사용할 수 있습니까? 단위 테스트에서 이것을 재현 할 수 있습니까? 그렇다면 다른 JVM에서 실행하여 어떤 결과가 발생하는지보십시오.

+0

Weblogic 9.2.3, 그리고 최신 버전을 사용하는 것은 불행히도 단기간에 옵션이 아닙니다. JDK 1.5.0.16도 도움이된다. –

+1

이 자바 버그는 객체 직렬화가 어떻게 작동 하는지를 약간 설명합니다. 전체 개체를 버퍼에 보관해야하는 이유를 설명합니다. 귀하의 경우, 큰 개체를 작은 개체로 분할하고 ObjectOutputStream에서 reset()을 호출하여 해체해야합니다. http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4363937 – wolfcastle

0

I (즉 - 내가 생각하는 JRockit) 웹 로직 모르는 특히 직렬화 : 솔직히 ByteArrayOutputStreams 사용하는 이유를 볼 수 없습니다 ... 당신이 더 많은 제어가 필요한 경우

당신은 java.io.Externalizable을 구현할 수 있습니다 객체를 직렬화하는 방법 - 직접 많은 수의 클래스가있는 경우 읽기/쓰기 메서드를 직접 작성하지 않으려면 완전히 다른 직렬화 시스템 (예 : Terracotta)으로 전환하십시오.

2

이렇게 많은 수준에서 잘못되었습니다. 이것은 직렬화의 방대한 남용입니다. 직렬화는 대부분 객체를 임시로 저장하기위한 것입니다. 예를 들어,

  1. tomcat 서버 다시 시작 사이의 세션 개체입니다. 자바의 직렬화 객체의 장기 저장 (없음 버전 지원)을 처리하기 위해 노력을하지 않으며 아니라 큰 개체를 처리 할 수 ​​

의 JVM 사이

  • 전송 객체 (웹 사이트에서로드 밸런싱).

    그래서 뭔가 큰 일을 위해, 내가 먼저 몇 가지 조사를 제안 :

    1. 하면 전체 JVM 힙을 유지하기 위해 노력하고 있지 않은지 확인합니다.
    2. '일시적'이라는 레이블이 붙을 수있는 멤버 변수를 찾으십시오. 직렬화 (서비스 개체에 대한 참조가있을 수 있음)
    3. 개체가 너무 많아서 개체가 지나치게 많을 가능성을 고려하십시오.

    실제로 모든 것이 맞으면 java.io.Serialization에 대한 대안을 조사해야합니다. java.io.Externalization을 통해 더 많은 제어권을 얻는 것이 효과적 일 수 있습니다. 하지만 json 또는 xml 표현과 같은 것을 제안합니다.

    업데이트 :

    가 조사 :

    1. google's protocol buffer
    2. facebook's Thrift
    3. Avro
    4. Cisco's Etch

    Take a look at this benchmarkings as well.

  • +0

    이러한 세 가지 사항이 모두 고려되고 제거되었습니다. 메모리에있는 객체의 크기를 줄이는 것은 쉽지 않습니다. CMS에는 최소한 500,000 개의 컨텐트 항목이 저장되어 있습니다.추론 한대로 응용 프로그램 재시작 속도를 높이기 위해 디스크에 지속됩니다. 디스크의 크기를 줄일 수있는 대체 표현의 사운드를 좋아합니다. 그러나 직렬화 동안 사용 된 메모리에 어떤 차이가 있습니까? –

    +1

    교차 재시작 속도 향상 문제는 새 버전의 코드가 있기 때문에 서버를 다시 시작한 것으로 추정됩니다. 새 버전은 직렬화 된 이전 버전을 안정 적으로 직렬화 해제 할 수 없음을 의미합니다. 그렇게 효과적으로 아무것도 얻지 못합니다. – Pat

    관련 문제