일부 시스템 간의 상호 작용을 위해 GZIP 압축을 구현하고 있습니다. 이 시스템은 Java와 C#으로 작성되었으므로 GZIP 스트림은 표준 라이브러리를 지원하므로 양쪽에서 사용되었습니다.힙 오버플로없이 큰 (압축되지 않은 70MB) 바이트 스트림의 압축을 어떻게 처리해야합니까?
C# 측에서 모든 것이 가장 큰 테스트 파일 (압축되지 않은 70MB)까지 작동하지만 힙 공간이 부족한 Java 문제가 발생합니다. 힙 크기를 IDE의 용량으로 늘려 보았지만 문제는 해결되지 않았습니다.
Java 코드를 시도하고 최적화하기위한 몇 가지 조치를 취했지만 데이터가 힙에 겹치지 않도록하는 방법은 없습니다. 이것을 처리 할 수있는 좋은 방법이 있습니까? 아래는 현재 (작은 스트림 작업) 솔루션의 하위 집합입니다.
편집 : @MarkoTopolnik의 권장 사항에 따라 수정 된 코드. 변경 사항으로 충돌 전 1700 만자를 읽습니다.
public static String decompress(byte[] compressed, int size)
{
GZIPInputStream decompresser;
BufferedReader reader;
char buf[] = new char[(size < 2048) ? size : 2048];
Writer ret = new StringWriter(buf.length);
decompresser = new GZIPInputStream(new ByteArrayInputStream(compressed), buf.length);
reader = new BufferedReader(new InputStreamReader(decompresser, "UTF-8"));
int charsRead;
while((charsRead = reader.read(buf, 0, buf.length)) != -1)
{
ret.write(buf, 0, charsRead);
}
decompresser.close();
reader.close();
return ret.toString();
}
코드는
ArrayList
에서 760 만 개 문자 위에 작은 타격 후 다이와 스택 트레이스는
ArrayList.add()
호출 원인임을 나타낸다 (확장되는 내부 어레이를 트리거링 후 실패).
위에서 편집 한 코드를 사용하면 AbstractStringBuilder.expandCapacity()
을 호출하면 프로그램이 종료됩니다.
동적 배열을 구현하는 데 메모리가 덜 비싼 방법이 있습니까? 아니면 압축 해제 된 스트림에서 String을 가져 오기 위해 사용할 수있는 완전히 다른 접근 방식이 있습니까? 어떤 제안이라도 대단히 감사하겠습니다!
기존의 프레임 워크 제약으로 인해 옵션이 아닌 경우가 많습니다. 나는 OP에 그런 사건이 있다고 말하고 싶다. –
예, 이전 프레임 워크로 구현할 방법이 없습니다. 함수는 String을 반환해야하며 주어진 바이트 배열을 압축해야합니다. 이러한 제약 조건을 통해 솔루션을 구현할 수있는 방법을 발견 할 수 있습니다. – Dan
당신 말이 맞아요. 모든 플러그인이 설치된 VisualVM을 사용하여 메모리가 소비되는 곳을 확인하는 것이 좋습니다. 프레임 워크를 버릴 때가 왔습니다. – duffymo