2009-10-26 9 views
9

로드 - 테스트하려고하는 서버 구성 요소가 있습니다. 서버에 대한 모든 연결은 TLS 1.0을 사용합니다. 다음과 같이Sun의 Java SSL 구현에서 메모리 누수가 발생합니까?

Full TLS handshake to the server 
send a request 
read reply 
close connection 
repeat ad nauseam 

내 가상 머신은 다음과 같습니다 :

Java(TM) SE Runtime Environment (build 1.6.0_16-b01) 
Java HotSpot(TM) Server VM (build 14.2-b01, mixed mode) 

내가 메모리 누수가 내가 원하는대로 본질적으로 많은 스레드에서이 작업을 수행하는 간단한 테스트 프로그램이 있습니다. 내 서버를 많이 테스트 할 때 초당 약 1MB의 메모리 사용량이 증가하여 OutOfMemoryException으로 15-20 분 후에 차단됩니다.

Netbean의 프로파일 러에서 실행하여 TLS API 내에서 메모리 증가가 심한 것으로 나타났습니다.

비슷한 경험을 한 사람이 있습니까? 내 수준에서 구현할 수있는 해결 방법이 있습니까?

편집.

.java.io.ByteArrayOutputStream.<init>(int) 
..com.sun.net.ssl.internal.ssl.OutputRecord.<init>(byte, int) 
...com.sun.net.ssl.internal.ssl.OutputRecord.<init>(byte) 
....com.sun.net.ssl.internal.ssl.AppOutputStream.<init>(com.sun.net.ssl.internal.ssl.SSLSocketImpl) 
.....com.sun.net.ssl.internal.ssl.SSLSocketImpl.init(com.sun.net.ssl.internal.ssl.SSLContextImpl, boolean) 
......com.sun.net.ssl.internal.ssl.SSLSocketImpl.<init>(com.sun.net.ssl.internal.ssl.SSLContextImpl, java.net.Socket, String, int, boolean) 
.......com.sun.net.ssl.internal.ssl.SSLSocketFactoryImpl.createSocket(java.net.Socket, String, int, boolean) 
<my code> 

보다 내가 넣을 수 있습니다 많은 ...이 긴 것 같습니다 요청으로, 여기에이 바이트 []를 많이 생성하는 프로파일 호출 추적입니다. 프로파일 러가 저를 준다 당신에게 진입 점을 말해주지 :

....com.sun.net.ssl.internal.ssl.AppOutputStream.<init>(com.sun.net.ssl.internal.ssl.SSLSocketImpl) 
....com.sun.net.ssl.internal.ssl.HandshakeOutStream.<init>(com.sun.net.ssl.internal.ssl.ProtocolVersion, com.sun.net.ssl.internal.ssl.ProtocolVersion, com.sun.net.ssl.internal.ssl.HandshakeHash, com.sun.net.ssl.internal.ssl.SSLSocketImpl) 
....com.sun.net.ssl.internal.ssl.SSLSocketImpl.sendAlert(byte, byte) 
..com.sun.net.ssl.internal.ssl.AppInputStream.<init>(com.sun.net.ssl.internal.ssl.SSLSocketImpl) 
..com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake() 
..com.sun.net.ssl.internal.ssl.HandshakeInStream.<init>(com.sun.net.ssl.internal.ssl.HandshakeHash) 
+2

좀 더 구체적인 프로파일 링 결과를 제공 할 수 있습니까? 누수가 반드시 TLS에서 나오는 것은 아니며 코드에있을 수도 있습니다. –

+1

이 동작을 나타내는 가능한 가장 작은 프로그램을 만들어 질문에 추가하십시오. –

답변

4

가까운 연결을 보았습니까? 대부분이 여하튼 여전히 열려 있습니다. 1Mb는 몇 가지 추가 스레드를 노래합니다. 그러나, 나는 정확히 무엇이 이유인지 확신하지 못한다.

+0

본 적이 있습니다. Executors.newScheduledThreadPool'을 사용하고 있으므로 주어진 시간에 얼마나 많은 쓰레드가 실행되고 있는지 완전히 제어 할 수는 없습니다. 즉, 프로파일 러 결과에 따르면 대부분의 메모리는 byte []로 표시됩니다. – malaverdiere

+0

클라이언트 연결이 제대로 처리되고 연결이 닫혔는지 다시 한 번 확인합니다. 좋은 생각. – malaverdiere

+0

그래, 그게 큰 차이를 만들었 어! IOException을 잡아 냄으로써 연결이 끊어 졌음에도 불구하고 SSLSocket을 닫지 않았습니다 ... – malaverdiere

8

모든 SSL 연결이 후 임시 암호화 키를 협상 할 때 핸드 셰이크의 오버 헤드를 줄이기 위해 별개의 TCP 연결을 통해 재사용 할 수있는 SSL 세션과 연관된 실제 TCP 연결이 설정되었습니다. 클라이언트가 어떻게 든 새 세션 생성을 강제 할 수 있으며 Java 6의 기본 구성은 1 시간 동안 세션을 무제한으로 캐시하는 것으로 보이기 때문에 쉽게 메모리 문제가 발생할 수 있습니다.

서버 소켓에서 getSession(). getSessionContext()를 사용하여 SSLSessionContext를 가져 와서 setSessionTimeout을 사용하여 캐시 크기를 setSessionCacheSize 및 timeout (초)으로 설정하여 서버 소켓에 대한 이러한 설정을 조작 할 수 있습니다. 시스템 속성을 통해 기본 구성을 변경하는 것이 가능할 것으로 예상 했었지만 그 문서를 찾을 수는 없습니다. 아마 당신은 내가 한 것보다 조금 더 인터넷 검색을 통해 스스로를 찾을 수 있습니다.


올바른 세션 컨텍스트의 한계를 설정 하시겠습니까? 서버 소켓에서 도달 할 수있는 컨텍스트에 대해 오인되었습니다. 당신은 서버 소켓 생성하기 전에의 SSLContext를 통해 설정해야이 제한없이

SSLContext sslContext = SSLContext.getDefault(); 
sslContext.getServerSessionContext().setSessionCacheSize(1000); 
SSLServerSocket ss = (SSLServerSocket) 
    sslContext.getServerSocketFactory().createServerSocket(<port>); 

를, 각 캐시 된 SSL 세션 솔기가 어딘가에 7-800 바이트를 사용하는 등, 당신의 기억 "누출"을 재현하기 쉬웠다 힙 메모리 세션 수를 제한하면 내 서버가 약 15 분 동안 스트레스를 받고 실행 중이며 3-4MB의 힙 메모리 만 사용하고 있습니다.

+0

한계를 1000 세션으로 설정했습니다. 충돌 이전의 커브는 이전처럼 가파르지 않습니다 (지금은 계단처럼 보입니다). 이것이 도움이됩니다. 그럼에도 불구하고 여전히 충돌합니다. – malaverdiere

+0

게시물 편집에서 제안한 코드 스 니펫을 사용해 보셨습니까? – jarnbjo

+2

기본 시간 초과 (즉, 24 시간)가 86400 초이며 기본 캐시 크기를 설정할 수 있습니다. w /'-Djavax.net.ssl.sessionCacheSize = xxx' 속성 – bestsss

1

1MB는 ​​스레드를 만드는 데 필요한 메모리입니다 (추가 또는 필요하지 않음).

해당 클래스 나 패키지의 버그 목록에 항목이 있습니까? 첫 번째 단계는 그것을 점검하는 것입니다.

두 번째 단계는 Sun의 문제가 아니라 코드에 문제가 있다고 가정하는 것입니다. 자바 JDK에서 일반적으로 사용되는 클래스가 전 세계 사용자들에 의해 강타 당했기 때문입니다. 오류가 발생하면 지금까지 불이 들어 왔을 것입니다.

JDK 코드가 버그가 없다고 말하는 것은 아닙니다. 코드를 먼저 의심해야합니다.

프로파일 러 및 측정 값 얻기 짐작하지 마라.

+1

+1 - 먼저 자신의 코드를 의심하십시오 –

+0

제가 말했던 것처럼 프로파일 러에서 실행했습니다. 모든 오버 헤드는 SSL 구현 내에서 깊은 바이트 []로 인한 것입니다. – malaverdiere

0

실행중인 하드웨어는 무엇입니까? netstat을 수행하고 연결 상태를 확인할 수 있습니까?

톰캣을로드 테스트 한 결과 Solaris에서 1GB 힙을 사용하여 몇 시간 동안 500 개의 새 SSL 요청/초를 달성하는 데 문제가 없었습니다. 또한 컨테이너에서 실행중인 스레드 수를 모니터 할 수 있습니다.

관련 문제