2010-12-13 8 views
2

Oracle 데이터베이스에서 스트레스 테스트의 일부로 오랫동안 코드를 실행하고 Java 버전 "1.4.2"를 사용하고 있습니다. 간단히 말해서, 내가하고있는 일은 다음과 같습니다.내 코드의 메모리 부족 예외

while(true) 
{ 
    Allocating some memory as a blob 
    byte[] data = new byte[1000]; 
    stmt = fConnection.prepareStatement(query); // [compiling an insert query which uses the above blob] 
    stmt.execute(); // I insert this blob-row in the database. 
stmt.close(); 

} 

이제이 테스트를 8-10 시간 동안 실행하고 싶습니다. 그러나 분명히 약 15million 레코드를 삽입 한 후에 나는 java.lang.OutOfMemoryError

을 -Xms512m -Xmx2g와 함께 실행하고 있습니다. 나는 더 높은 값을 사용하여 시도하지만 난 그렇게 많은 하드웨어를 갖고있는 것 같다 해달라고하지 어느 쪽도 아니 나는 그것이 REQ 생각하십시오

java -Xms512m -Xmx4g -jar XX.jar 
    Invalid maximum heap size: -Xmx4g 
    The specified size exceeds the maximum representable size. 
    Could not create the Java virtual machine. 
    java -Xms2g -Xmx3g -jar XX.jar 
    Error occurred during initialization of VM 
    Could not reserve enough space for object heap 
    Could not create the Java virtual machine. 

난이 다중 스레드 프로그램으로 실행합니다. 이렇게 arnd 10 개의 실은 삽입을하고있다.

아마도이 프로그램을 이식 할 수있는 방법이있을 수 있습니다. 나는 이것을 8-10 시간 대신 15-20 시간 동안 달리기로 결심했다면 어떨까요?

편집 : stmt.close를 추가했습니다. 이미 코드에서 사용하고 있습니다. 의견에 따라 일부 변경

감사

PS : NDA

의 코드 벡를 게시하지 못할 미안
+0

프로세스에 대한 시스템 하드 제한을 확인 했습니까? 사용중인 쉘에 따라 limit 또는 ulimit을 사용하여 확인할 수 있습니다. – Pirooz

+0

"당신 생각"? 프로파일 러를 나가서 실제로 무슨 일이 일어나는지보십시오. –

+0

예외는 코드 행에서 byte []를 수행합니다. data = new byte [1000]; – codeObserver

답변

1

난 당신이 그렇게 된 PreparedStatement에 할당 된 메모리가 될 것입니다

stmt.close(); 

을 추가해야한다고 생각 해방.

+0

안녕하세요, thmx, 이미 stmt.close()가 있습니다. 그러나 문장을 한 번만 준비하고 수백만 시간을 사용합니다. 그래서 메모리는 문장에 한 번만 할당됩니다. – codeObserver

+0

@ p1 : 게시 한 코드에 따라 진술서를 한 번만 준비하지 마십시오 ... – SimonJ

+0

예, 나중에 변경 한 내용입니다. 그러나 나는 항상 stmt.close()를 사용했다. – codeObserver

0
java -Xms2g -Xmx3 -jar XX.jar 
Error occurred during initialization of VM 
Incompatible minimum and maximum heap sizes specified 

java -Xms2g -Xmx3g -jar XX.jar 

가 얼마나 많은 메모리 당신이 당신의 상자에 있나요 시도? 32 비트 또는 64 비트 JVM을 실행하고 있습니까?

+0

시도하고 질문에 그것을 업데이 트되었습니다.위로 사용하고있는 것을 보여줍니다 Mem : 3891380k total 스왑 : 1048568k total – codeObserver

+1

얼마나 많은 메모리가 사용 중인지 묻지 않았고 시스템에서 사용 가능한 메모리가 얼마나되는지 질문했습니다. 그리고 어떤 JVM을 실행하고 있습니까? 명령 행에서 java -version을 시도하고 결과를 질문에 넣으십시오. –

+1

나는 이것이 그의 문제라고 생각하지 않습니다. 그의 응용은 단순히 많은 양의 기록을 스트레스 테스트로 삽입하는 것입니다. 이렇게하면 더 많은 양의 메모리가 필요하지 않아야하며 더 많은 메모리를 제공하면 문제가 해결됩니다. –

6

기본적으로, 나는 당신이 잘못 짚었 생각 :

  • 에 상관없이이를 할당하는 속도, 도달 할 수없는 객체의 할당을 해제하지 않으려면 관리하는 JVM/GC. 기존의 비 동시성 GC를 실행하는 경우 JVM은 GC가 메모리를 할당 해제 할 때까지 다른 작업을 중지합니다. 동시 GC를 사용하도록 JVM을 구성한 경우 GC 및 일반 작업자 스레드를 동시에 실행하려고 시도하고 유지할 수없는 경우 "모든 것을 중지하고 수집"동작으로 되돌립니다.

  • 메모리가 부족한 것은 응용 프로그램 (또는 사용중인 라이브러리/드라이버)의 메모리에 누수가 있기 때문입니다. 즉, 응용 프로그램이 더 이상 필요하지 않더라도 객체로 인해 도달 할 수있는 요소가 있습니다.

주석에서 지적했듯이 메모리 프로파일 러/힙 덤프를 사용하여 체계적으로이 문제를 해결해야합니다. 무작위로 변경하거나 GC를 비난하면 문제를 해결하기가 쉽지 않습니다.

(내가 라고 말하면 "stmt를 사용했습니다.당신이 finallyclose 통화를 보류하지 않으면

PreparedStatement stmt = ... 
    try { 
     stmt.execute(); 
     // ... 
    } finally { 
     stmt.close(); 
    } 

다음 당신이 호출되지 않습니다 수 있습니다 : 모든 시간 ") (닫기, 나는이 코드를 이런 식으로 뭔가를 보이는 것을 의미한다고 가정 close 일부 예외가 execute 통화 중 또는 그와 close 호출 사이에 발생됩니다 경우마다. 특히, close가 호출되는되지 않을 수 있습니다 ... 그리고 그 누수가 발생합니다.)

+0

질문에 자바 버전 업데이트 됨 while 루프의 각 반복에서 닫히는 것을 의미합니다. 이 방법은 매 반복마다 stmt에 할당 된 메모리를 없애고 마침내 닫히기 전에 수십억 개의 할당을 기다리지 않습니다. 그러나 루프에 prep stmt가있는 경우에는 각 반복을 stmt로 컴파일하는 것이 비효율적이라고 생각하며이를 변경합니다. 그러나 나는 던져지고있는 어떤 다른 예외도 보지 않는다. 나는 당신의 관점을보고 마침내 블록을 추가했습니다. – codeObserver

+0

@ p1 - IMO, 예외를 던질 수있는 방법을 상상할 수는 없지만 'finally'블록에서 리소스 핸들을 해제하는 것이 "우수 사례"입니다. (그리고 물론, 당신의 메모리 누출이나 누수가 다른 곳에서있을 가능성이 있습니다 ...) –

1

코드 또는 라이브러리에 누수가있는 경우 메모리 분석기 (MAT)는 무료입니다 Java 메모리 덤프 파일을 탐색하기위한 Eclipse 기반 앱. 지침에는 덤프 파일을 삭제하는 방법이 포함되어 있습니다. http://www.eclipse.org/mat/

+0

링크마다 사용하려고했지만 어디서나 생성 된 (.hprof) 파일을 보지 못했습니다. 언급 된대로 구성 인수에 -XX : + HeapDumpOnOutOfMemoryError를 사용했습니다. 어떤 제안? – codeObserver

+0

hprof 파일을 가져 오는 데는 몇 가지 방법이 있습니다. 필자가 선호하는 설정은 사용중인 설정이며, 파일은 '응용 프로그램의 현재 작업 디렉토리'에 있어야합니다. 항상 정의하기 쉽지는 않습니다 :) 파일 시스템에서 검색을 실행 해 보았습니까? –

0

편집 :은 알려진 Oracle 드라이버의 문제가 될 수 있음을 보인다 http://www.theserverside.com/discussions/thread.tss?thread_id=10218


그냥 롱샷 , 당신이 여기에 일반 JDBC를하고있는 알고 있지만, 당신은 어떤 강화제가 hapen 경우 (AspectJ, Hibernate, JPA) Perm gen의 유출 가능성이있는 경우, -XX:MaxPermGen=256m을 안전한면으로 설정하십시오.

jvisualvm 메모리 프로파일 러 및 jprofiler (시험 사용 가능) 빨리 실행합니다.

1

이 실행은 OracleConnection NativeMemory에서 발생합니다. NIO 작업에서 oracle jdbc guys는 메모리의 기본 부분을 사용하기로 결정했습니다. 대부분이 쿼리를 너무 자주 실행하면 응용 프로그램이 덤프됩니다. 이 문제를 해결하려면 jdbc의 캐시 크기를 늘리거나 시간 간격으로 애플리케이션을 다시 시작하십시오.