2013-11-04

java.io.IOException: error=12, Cannot allocate memory? WTF?!

자바의 유서깊은(?) 골칫거리로, 자바에서 fork() + exec() 하는 방식에 문제가 있기 때문이다.
(자세한 내용은 여기를 참고하면 좋다.)

위 링크에서 4가지 해결책이 나온다.
  1. 닥치고 메모리 증설
  2. fork() 호출시 swapfile을 추가하도록 꼼수 사용
  3. 리눅스: sysctlvm.overcommit_memory 속성을 1로 설정
  4. POSIX 호환 시스템: fork() + exec() 대신 posix_spawn() 사용하기

리눅스라면 vm.overcommit_memory=1 이 아무래도 빠르고 편하겠지만, 동작방식이 후덜덜하므로 overcommit이 일어날 때 커널에서 노는 메모리를 수거하는데, 이 때 어떠한 확인도 없이 막무가내로 수거하므로 잠자고 있는 멀쩡한 다른 프로세스의 메모리를 수거할 수 있다! 미션 크리티컬한 시스템에는 그냥 하지마라. 그런 시스템이라면 2웨이 이상일테니 그냥 닥치고 1번이 더 정신건강에 좋을 것이다. 돈은 좀 많이 깨지겠지만 내가 알 게 뭐야...

또한 자바의 fork() + exec()posix_spawn()으로 교체해주는 java_posix_spawn이 개발되어 있으므로, 이를 고려해보는 것도 좋을 것이다. 하지만 실제로는 posix_spawn()을 사용하지 않는다는게 함정vfork() 쓴댄다.

vm.overcommit_memory 관련 문서는 레드햇 문서노벨 문서를 보면 대략 좋다.


2015-02-23:
리눅스에 zram이라는게 있는데, 써본 결과 매우 좋소!
zram 쓰기 전에는 메모리 10그램으로도 헥헥대던게, zram 쓰고 난 다음부터는 메모리에 여유가 생겼다.
물논 CPU가 그만큼 일을 더 하게 되지만 내가 알 게 뭐야...
Share:

0 개의 댓글:

댓글 쓰기