티스토리 뷰
이클립스로 javaEE 어플리케이션을 개발하다보면, 가끔 의도적으로든, 실수로든 실행중인 jar 파일을 삭제하거나 교체하는 경우가 있다.
놀라운 것은 이때의 동작이 HP-OS, linux, Windows의 동작이 모두 다르다는 것이다.
일단 윈도우즈 먼저 살펴보자.
윈도우즈는 어떤 파일을 삭제하기 굉장히 까다롭다. 어떤 프로세스가 read lock을 파일에 걸게 되면, 운영체제가 파일락을 걸어버린다. 그리고 삭제할 때, 삭제가 되지 않도록 한다. 가장 대표적인 예가 토렌트와 악성코드가 있다. 토렌트에서 배포중이거나, 다운로드를 받고 있는 파일을 토렌트가 아닌 윈도우 창에서 삭제하려고 하면 삭제가 되지 않는 경험이 있을 것이다. 혹은, 어떤 파일이 악성코드에 감염되었는데, 해당 파일을 삭제하려고 하니, 삭제가 안되는 경험도 있을 것이다. 이로 인해 unlocker.exe 같은 프로그램이 돌아다니는 것이다.
윈도우즈에서는 어떤 파일에 대해 lock이 잡혀있는 경우에 Resource Monitor라는 프로그램을 통해 확인할 수 있다.
아래 그림에서 자세히 확인해보자.
위 그림은 제우스 이클립스 플러그인을 활용해 개발할 때 jar 파일에 락이 잡여있는 것을 보여주고 있다.
이클립스 플러그인으로 개발을 하지 않더라도, 위와 같이 파일락을 잡게 되어 있다.
위 이미지에서 WEB-INF/lib의 디렉토리에 있는 spring-webmvc를 pid가 584404인 java 프로세스가 열고 있 다는 것을 리소스 모니터를 통해 확인할 수 있다. 또한, 이 자바프로세스가 제우스 서버임을 확인할 수 있다.
자바 ee 서버에서는 어플리케이션을 디플로이할 때, jar 파일을 읽게 된다. 이는 클래스로더를 구성하고, jar 파일 내에 지정된 annotation을 어플리케이션에 적용할 수 있게 해준다든지, web-fragment.xml의 설정을 적용하는 등의 목적을 가지고 jar 파일을 열고 닫는다. 그리고 최종적으로는 classloader를 위해 JarInputStream을 통해 jar 파일을 열어놓게 된다.
클래스로더 구현상, 어플리케이션이 디플로이되어 있는 동안에는 jar 파일을 계속 열어두어야 동적으로 클래스로딩을 하고, 예기치 못한 동작을 하는 것을 막을 수 있다.
윈도우즈에서는 만약에 이 파일을 삭제하려고 하면, 아래와 같이 메시지가 뜰 것이다.
서블릿에서 lock을 잡고 있기 때문에 삭제할 수 없다고 메시지가 뜬다. 물론, 이런 경우에는 redeploy를 권유하는 메시지가 뜬다. 어플리케이션 클래스로더를 다시 올려야 하기 때문이다.
위 경로를 보면 알겠지만, 실제 exploded 되어있는 어플리케이션이 있는 디렉토리가 아닌, eclipse의 플러그인을 위한 디렉토리로 복사해 사용하도록 되어 있다. lock 또한 이 쪽에만 잡혀있어, 이클립스 UI 상에서 jar 파일을 삭제하는 경우에 삭제가 된다. 그러나, 이를 동기화 시키는 과정에서, plugin의 디렉토리에 있는 jar를 삭제하려고 하지만, 락이 잡혀 있어 삭제가 되지 않는 모습이다.
그렇기 때문에 이런 경우에는 undeploy 후에 deploy 하도록 유도를 한다. undeploy 할 때, jar 파일에 대한 참조를 멈추기 때문이다.
그렇다면, 리눅스에서는 어떻게 동작할까?
사실 리눅스에서도 동일하게 운영체제에서 락을 잡아준다. 그러나, UI 상에서 파일을 삭제하면, 삭제가 된다. 이는 눈으로만 삭제가 되는 것이다. 실제로 자바의 JarInputStream이나, FileInputStream(둘간에 상속관계가 없다는 점에 유의한다)을 사용하는 경우에는 fd에 대해 락을 잡고 있고, 리눅스 내부적으로는 락이 풀릴 때까지 fd를 계속 참조 및 유지한다. 그렇기 때문에 jar 파일을 교체한다든가, 삭제한다든지의 행동을 해도 우리의 눈에만 삭제된 것으로 보일 뿐, 실제로는 해당 파일이 존재한다. 삭제에 대한 반영은 process에서 fd에 대한 참조를 중단할 때 비로소 반영이 된다.
윈도우즈와의 차이는, GUI 상에서 즉각적으로 반영을 해주는지에 대해서만 있는 것이고, 사실 운영체제 단에서는 동일하게 락을 잡고 동작하고 있는 것이다.
HP-OS는 특이한데, 삭제하거나 교체를 하면 fd 자체를 날려버린다. 정말 과감한 OS이다. 그렇기 때문에 파일을 삭제한 이후에 동적 클래스로딩을 시도하면 ClassNotFoundException이 발생한다. 파일에 대한 fd마저 삭제해버려서 InputStream을 통해 jar 파일을 읽어오지 못한다. 정말 과감한 정책이다.
오늘의 결론은 jar 파일을 수정하고 반영하고 싶으면 JRebel을 사든지, undeploy 후 deploy를 하든지 하라는 것이다. 이는 피할 수 없다.
'개발 > 제우스' 카테고리의 다른 글
서블릿에서 post body를 어떻게 읽는가? (0) | 2019.09.12 |
---|
- Total
- Today
- Yesterday
- 안전신문고
- 한국교통안전공단
- 현금영수증
- ouath2
- Thymeleaf
- springboot3
- 티스토리챌린지
- 전세사기
- JPA
- 오블완
- k베뉴
- 홈택스
- Azure
- springboot
- 토스페이
- ORM
- Request
- 이륜차
- 공익제보단
- 알리익스프레스
- 포상금
- tomcat
- 탈세
- 부가가치세
- 광군제
- Java17
- Spring
- 알리
- java
- n+1
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |