Java 스택 오버플로 오류-Eclipse에서 스택 크기를 늘리는 방법은 무엇입니까?
Eclipse에서 Java로 작성한 프로그램을 실행하고 있습니다. 이 프로그램은 매우 큰 입력에 대해 매우 깊은 수준의 재귀를 가지고 있습니다. 작은 입력의 경우 프로그램이 잘 실행되지만 큰 입력이 주어지면 다음 오류가 발생합니다.
Exception in thread "main" java.lang.StackOverflowError
Java 스택 크기를 늘려이 문제를 해결할 수 있으며 그렇다면 Eclipse에서 어떻게 수행합니까?
최신 정보:
@Jon Skeet
코드는 데이터 구조를 구축하기 위해 파스 트리를 재귀 적으로 순회합니다. 예를 들어 코드는 구문 분석 트리의 노드를 사용하여 일부 작업을 수행하고 노드의 두 자식에서 자신을 호출하여 결과를 결합하여 트리에 대한 전체 결과를 제공합니다.
재귀의 총 깊이는 구문 분석 트리의 크기에 따라 다르지만 재귀 호출 수가 1000 개에 도달하면 코드가 실패하는 것처럼 보입니다 (더 큰 스택없이).
또한 작은 입력에 대해 작동하므로 버그로 인해 코드가 실패하지 않는다고 확신합니다.
애플리케이션의 구성 실행을 엽니 다 (구성 실행 / 실행 ...을 누른 다음 'Java 애플리케이션'에서 애플리케이션 항목을 찾습니다).
인수 탭은 텍스트 상자가 VM 인수를 입력 -Xss1m
(또는 최대 스택 크기에 대한 더 큰 매개 변수). 기본값은 512KB입니다 (SUN JDK 1.5-공급 업체와 버전간에 차이가 있는지 알 수 없음).
그것은 수 있습니다 스택의 크기를 증가시켜 경화 수 -하지만 더 나은 솔루션은 너무 많은 재귀 방지하는 방법을 해결하는 것입니다. 재귀 솔루션은 항상 반복 솔루션으로 변환 될 수 있습니다. 그러면 코드가 더 큰 입력으로 훨씬 더 깔끔하게 확장됩니다. 그렇지 않으면 얼마나 많은 스택을 제공해야하는지 추측하게 될 것입니다. 이는 입력에서 분명하지 않을 수도 있습니다.
그건 그렇고, 코드의 버그가 아니라 입력의 크기로 인해 실패하고 있다고 확신합니까? 이 재귀는 얼마나 깊습니까?
편집 : 좋아, 업데이트를 본 후 재귀를 사용하지 않도록 개인적으로 다시 작성하려고합니다. 일반적으로 Stack<T>
"아직해야 할 일"을 갖는 것은 재귀를 제거하는 좋은 시작점입니다.
-Xss1024k
VM 인수에 플래그 를 추가합니다 .
예를 들어 mb
를 사용하여 스택 크기를 늘릴 수도 있습니다 -Xss1m
.
XSOM 라이브러리를 사용하여 스키마 정의 파일 (XSD)을 구문 분석하는 동안에도 동일한 문제가 있습니다.
나는 스택 메모리를 최대 208Mb까지 늘릴 수 있었고 그 결과 heap_out_of_memory_error
320mb까지만 늘릴 수 있었다.
최종 구성 -Xmx320m -Xss208m
이었지만 다시 한동안 실행되어 실패했습니다.
내 함수는 스키마 정의의 전체 트리를 반복적으로 인쇄합니다. 놀랍게도 출력 파일은 50Mb의 스키마 정의 라이브러리 (ISO gml)를 사용하는 4Mb (Aixm 라이브러리)의 정의 파일에 대해 820Mb를 넘었습니다.
그것으로 나는 재귀를 피한 다음 반복과 출력을 나타내는 다른 방법을 시작해야한다고 확신하지만 모든 재귀를 반복으로 변환하는 데 거의 문제가 없습니다.
JVM 매개 변수를 조정하려면 Eclipse 내부에 실행 구성이 있어야합니다.
F11 또는 Ctrl-F11로 프로그램을 실행 한 후 실행-> 구성 실행 ...에서 실행 구성을 열고 "Java 응용 프로그램"에서 프로그램을 엽니 다. "VM 인수"가있는 인수 창을 선택합니다.
이것은 -Xss1024k
가는 곳 입니다.
시작 구성이 작업 공간의 파일이되도록하려면 (오른쪽 클릭하여 실행할 수 있음) 공통 창을 선택하고 다른 이름으로 저장-> 공유 파일 확인란을 선택하고 시작 파일을 원하는 위치를 찾습니다. 저는 보통 CVS에 체크인 할 때 별도의 폴더에 보관합니다.
인수 -Xss
가 작업을 수행하지 않으면 다음에서 임시 파일을 삭제하십시오.
c:\Users\{user}\AppData\Local\Temp\.
이것은 나를 위해 트릭을했습니다.
일정한 공간을 사용하고 O (n)에서 실행되는 Morris in-order tree traversal을보세요 (일반 재귀 순회보다 최대 3 배 더 길지만 공간을 크게 절약합니다). 노드를 수정할 수있는 경우 루트로 역 추적 할 때 (노드에 직접 작성하여) 하위 트리의 계산 된 결과를 저장할 수 있습니다.
'IT TIP' 카테고리의 다른 글
Json.Net에서 PreserveReferencesHandling과 ReferenceLoopHandling의 차이점은 무엇입니까? (0) | 2020.12.14 |
---|---|
django 1.7 마이그레이션에 "테이블이 이미 있습니다"오류가 발생 (0) | 2020.12.14 |
Java에서 정적 메서드를 재정의하고 오버로드 할 수 있습니까? (0) | 2020.12.14 |
Ruby에서 스택 추적 객체를 얻는 방법은 무엇입니까? (0) | 2020.12.14 |
드래그 할 때 Google지도 이벤트 bounds_changed가 여러 번 트리거 됨 (0) | 2020.12.14 |