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:

2013-11-01

bash로 git의 빈 디렉토리 컨트롤하기

(2014-11-19: 좀 더 깔끔하게 수정)


git의 유일한 단점은 빈 디렉토리를 관리 할 수 없다는 것이다. 따라서 빈 디렉토리를 강제로 관리하려면 대충 아무 파일이나 던져놓는 수 밖에 없다.
MarkEmptyDirs라는 툴이 있기는 하지만, 깔기 귀찮다. 그냥 bash 있는거 쓰고 말지…

본문

find . -name ".emptydir" -delete; find -empty -type d | while read x; do touch "$x/.emptydir"; done

참 쉽죠?

주의: 이 스크립트에는 버그가 있지만 여백이 부족하므로 더 이상의 자세한 설명은 생략한다. 차마 귀찮아서라고는 못하겠다. 예제를 수정하면서 더이상은 naver!

해설

  1. 먼저 하위 디렉토리에서 .emptydir 파일을 찾아서 제거한다.
  2. 그 다음 빈 디렉토리를 찾아서 크기가 0인 .emptydir 파일을 생성한다.
참 쉽죠? (2)

응용

이클립스에 올려서 프로젝트에 먹일 수도 있다.

Run → External Tools → External Tools Configuration... 에 가서 새 프로그램 항목을 만든다.

  1. 이름은 적절하게 등록한다.
  2. Location: /bin/bash
  3. Working Directory: ${project_loc}
  4. Arguments: -c "find . -name \".emptydir\" -delete; find -empty -type d | while read x; do touch \"$x/.emptydir\"; done"

그 다음 Run → External Tools → Organize Favorites... 에서 방금 만든 것을 선택하면 툴바에서 한 방에 실행할 수 있다.

참 쉽죠? (3)
Share: