Windows Mobile 디바이스에서 실행되는 Java로 애플리케이션을 개발 중입니다. 이것을 달성하기 위해 우리는 Esmertec JBed JVM을 사용했습니다. JBoss JVM은 완벽하지는 않지만 지금 당장은 당황합니다. 최근 우리는 고객으로부터 OutOfMemoryErrors에 대한 불만을 제기하고 있습니다. 많은 것들을 가지고 놀고 난 후에 그 장치에는 충분한 여유 메모리 (약 4MB)가 있음을 발견했습니다.Java에서 많은 배열을 할당 할 때 메모리 단편화를 피하십시오.
OutOfMemoryErrors는 항상 코드의 같은 지점에서 발생하며 일부 문자를 추가하기 위해 StringBuffer를 확장 할 때 발생합니다. 이 영역 주위에 로깅을 추가 한 후, StringBuffer에 약 290000 자의 용량을 가진 것으로 나타났습니다. 내부 문자 배열의 확장 전략은 단순히 크기를 두 배로 늘려서 배열을 할당하려고 시도하는 것입니다. 약 580000 자. 나는이 시간에도 메모리 사용량을 출력했는데, 총 사용 가능한 메모리가 시간당 약 12MB까지 증가했기 때문에 3.8MB (메모리 사용량은 약 3.8MB)를 사용하고 있다는 것을 알았습니다. 따라서 확장 할 공간이 충분합니다. 따라서 응용 프로그램에서 OutOfMemoryError를보고하는 시점이 있습니다. OutOfMemoryError는 아직 무료로 제공되는 양을 감안할 때 많은 의미가 없습니다.
나는 지금까지 응용 프로그램의 작동에 대해 생각하기 시작했습니다. 기본적으로 나는 작은 XML Sax Parser 인 MinML을 사용하여 XML 파일을 파싱하고있다. XML의 필드 중 하나에는 약 300,000 자의 문자가 있습니다. 파서는 디스크에서 데이터를 스트리밍하며 기본적으로 한 번에 256 자만로드합니다. 그래서 문제의 필드에 도달하면 파서는 1000 번 이상 처리기의 'characters()'메서드를 호출합니다. 매번 256자를 보유하는 새로운 char []를 생성합니다. 핸들러는 단순히 이러한 문자를 StringBuffer에 추가합니다. StringBuffer의 기본 초기 크기는 12이며, 버퍼에 문자가 추가 될 때마다 새로운 char []를 만들 때마다 여러 번 커야합니다.
내 가정은 이전 char [] s가 가비지 수집 될 수 있기 때문에 충분한 여유 메모리가 있지만 어쩌면 새로운 배열에 적합 할만큼 큰 메모리 블록이 없을 수도 있습니다. 할당하십시오. JVM은 힙 크기를 확장 할만큼 똑똑하지 않을 수도 있습니다. 왜냐하면 바보 같기 때문에 필요하지 않다고 생각합니다. 여유 메모리가 충분하기 때문입니다.
내 질문은 : 누구든지이 JVM에 대한 경험이 있고 결론적으로 메모리 할당에 대한 내 가정을 확인하거나 반증 할 수 있습니까? 또한, 메모리를 조각화하지 않도록 배열의 할당을 유도하는 방법에 대한 아이디어가 있습니다 (제 가정가 맞다고 가정).
참고 : 물건은 이미 시도했다 :
- 본인은 StringBuffer와의 초기 배열 크기를 증가하고 많은 배열을 만들 필요가 없습니다 것이다 그래야 내가 파서의 읽기 크기를 increaed.
- StringBuffer의 확장 전략을 변경하여 특정 크기 임계 값에 도달하면 100 %가 아닌 25 % 만 확장 할 수 있도록 변경했습니다.
이 두 가지를 모두하는 것이 도움이되었지만 XML 데이터 크기를 늘리면 OutOfMemoryErrors가 상당히 낮은 크기 (약 350kb)로 나옵니다.
추가 할 사항 :이 테스트는 모두 해당 JVM을 사용하는 장치에서 수행되었습니다. Java SE 1.2 JVM을 사용하여 데스크탑에서 동일한 코드를 실행해도 문제가 발생하지 않거나 데이터 크기가 약 4MB에 도달 할 때까지 문제가 발생하지 않습니다.
편집 :
조금 나는 10M에 XMS를 설정입니다 도움이되었습니다 난 그냥 시도 또 다른 한가지. 따라서 JVM이 힙을 확장하지 않는 문제를 극복하고 오류가 발생하기 전에 더 많은 데이터를 처리 할 수있게되었습니다.
정말인가요? 이 기사는 객체를 가비지 수집하는 방법을 설명합니다. –
참조 개체가 없습니다. 내가 말했듯이, JVM이 많은 여유 메모리를보고하기 때문에 가비지 수집되지 않는 객체에 문제가 있다고 생각하지 않습니다. 여유 메모리가 어디에 있는지 질문입니다. 조각난거야? JVM이 새 배열을 할당 할 수없는 이유는 무엇입니까? – DaveJohnston