移除容器内核心JAR文件后Java应用仍运行的原理咨询
为什么Docker容器中删除正在使用的Java JAR文件后应用仍能运行?
核心原因在于Windows和Linux(Docker容器底层基于Linux)的文件系统对已打开文件的处理逻辑完全不同:
本地Windows的限制
Windows系统对正在被进程打开的文件会施加独占锁,任何试图删除、修改该文件的操作都会被直接阻止,这就是你看到“文件已在Java Platform Architecture中打开”提示的原因——系统不允许在文件被占用时变更它。
Docker容器(Linux)的文件处理机制
Linux采用的是inode与文件名分离的设计:
- 文件名只是指向文件实际数据(inode)的一个“链接”,删除文件名本质上只是移除了这个链接,而非直接删除文件数据。
- 当进程打开一个文件时,操作系统会给该文件的inode增加一个引用计数。只要引用计数大于0(比如Tomcat进程还在持有该文件的句柄),文件的实际数据就会保留在磁盘上,进程依然可以通过inode访问它,不受文件名是否存在的影响。
放到你的Tomcat场景里:
Tomcat启动时会加载/usr/local/tomcat/lib下的JAR文件,把类加载到内存,同时保持对JAR文件的打开句柄。当你删除JAR文件名后,Tomcat进程的引用计数还没归0,所以内存里的类能正常运行,网页自然可以正常访问。但如果此时重启Tomcat,因为找不到对应的文件名,就会启动失败。
验证方法(可选)
你可以在容器里执行lsof | grep <你的JAR文件名>,会看到Tomcat进程仍然持有该文件的句柄,状态会标记为deleted,这也能证明文件数据其实还没被真正删除。
内容的提问来源于stack exchange,提问作者Anguraj Dinesh
相关产品推荐
相关产品推荐

