2020년 12월 17일 목요일

modelmapper memory leak

최근 추가한 코드를 테스트하는 개발서버에서 아래의 에러 메시지가 발생했다.


java.lang.OutOfMemoryError: Direct buffer memory
        at java.nio.Bits.reserveMemory(Bits.java:694)
        at java.nio.DirectByteBuffer.(DirectByteBuffer.java:123)
        at java.nio.ByteBuffer.allocateDirect(ByteBuffer.java:311)
        at io.netty.buffer.UnpooledUnsafeDirectByteBuf.allocateDirect(UnpooledUnsafeDirectByteBuf.java:111)
        at io.netty.buffer.UnpooledUnsafeDirectByteBuf.(UnpooledUnsafeDirectByteBuf.java:68)
        at io.netty.buffer.UnsafeByteBufUtil.newUnsafeDirectByteBuf(UnsafeByteBufUtil.java:626)
        at io.netty.buffer.UnpooledByteBufAllocator.newDirectBuffer(UnpooledByteBufAllocator.java:65)
        at io.netty.buffer.AbstractByteBufAllocator.directBuffer(AbstractByteBufAllocator.java:179)
        at io.netty.buffer.AbstractByteBufAllocator.directBuffer(AbstractByteBufAllocator.java:170)
        at io.netty.buffer.AbstractByteBufAllocator.ioBuffer(AbstractByteBufAllocator.java:131)
        at io.netty.channel.DefaultMaxMessagesRecvByteBufAllocator$MaxMessageHandle.allocate(DefaultMaxMessagesRecvByteBufAllocator.java:73)
        at io.netty.channel.socket.nio.NioDatagramChannel.doReadMessages(NioDatagramChannel.java:243)
        at io.netty.channel.nio.AbstractNioMessageChannel$NioMessageUnsafe.read(AbstractNioMessageChannel.java:75)
        at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:642)
        at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:565)
        at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:479)
        at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:441)
        at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:858)
        at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:144)
        at java.lang.Thread.run(Thread.java:748)



추가한 부분은 udp 클라이언트 용도의 프로그램이었다. 


소스를 분석해 봤지만 문제되는 부분을 알 수 없었다.


visulavm을 이용해 모니터링을 해봤더니, classes의 Total loaded 개수가 계속 증가하면서, Metaspace 영역이 계속 증가하는 현상을 확인했다.

dump를 받아서 mat 프로그램으로 분석했다. 잘 사용할 줄은 몰랐지만 대충 보다 보니 modelmapper가 보인다. 뭐지...


'modelmapper 성능 이슈'로 검색해 봤더니, 이런 글을 찾았다. 


설마 하는 생각으로 modelmapper 부분을 제외했더니, 정상적으로 돌아왔다.


modelmapper는 예전부터 web 프로젝트에서 많이 사용했었기 때문에 이런 문제가 발생할 줄 몰랐다.


'modelmapper memory leak'으로 검색해서 더 알게 된 정보는 modelmapper는싱글톤으로 구성하여 사용하라는 것이다.


modelmapper를 많이 사용하지 않았기 때문에 전부 걷어내고 직접 지정하는 방식으로 변경했다.


이런 문제가 한 번 생기고 나니 modelmapper를 다시 사용하기 꺼려진다.


modelmapper memory leak으로 찾아 본 글

https://www.programmersought.com/article/1444628366/
https://better-dev.netlify.app/java/2020/10/26/compare_objectmapper/
http://modelmapper.org/user-manual/faq/
https://github.com/modelmapper/modelmapper/issues/375

2020년 12월 5일 토요일

오라클 접속이 되다 안되다 하는 현상.

스프링 기반으로 만든 소스에서 오라클 접속이 로컬에서 개발 할 때는 잘 되었다. 
문제는 개발서버에서는 연결 자체가 안됐다. 아예 안 되는 건 아니고, 가끔 연결이 될 때도 있었다. 
오류메시지가 연결되지 않은 것에 대한 메시지만 나오니 이 에러메시지로는 해결책을 찾기가 어려웠다.
이것저것 여러가지를 적용해 봤지만, 해결이 안 됬다. 다음날 다시 검색 시작. 해결법을 찾았다.

해결법은 이거였다.
-Djava.security.egd=file:/dev/./urandom
리눅스에서 오라클 jdbc 드라이버는 기본적으로 random 을 사용하는 데, random은 서버의 엔트로피를 사용하여 random 값을 생성한다고 한다. 여기서 엔트로피란 서버의 노이즈라고 한다.
노이즈는 서버의 디스크 읽기, 키보드 입력, 네트워크 패킷등이라고 한다.
random은 이런 엔트로피가 일정조건까지 채워져야 값을 생성해 준다고 한다. 이 기다림이 문제 였다. 반면 urandom 일정조건을 채우지 않고도 바로 값을 준다고 한다.

잘 이해가 안 가서 검색을 하니, 잘 정리된 블로그가 있었다.

역시 검색을 하려고 해도 뭘 알아야 검색을 할 수 있다.

결국 옵션 하나로 해결한 문제였지만 문제의 원인을 알 수 없을 때는 꽤 골치 아픈 문제였다.