我在 Ubuntu 12.04 服务器上有一个 Tomcat 6 服务器,内存为 4GB,JAVA_OPTS 如下
JAVA_OPTS="-Djava.awt.headless=true -Xms512M -Xmx512M -XX:PermSize=1024M -XX:MaxPermSize=1024M -XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled"
愚蠢的问题:如果我多次部署同一个 webapp(同一个 war 文件)(每次引用不同的 Postgres 数据库) - 如 server.com:8080/webapp1 server.com:8080/webapp2 等等...
我可以假设 Tomcat 将在多个 Web 应用程序之间缓存一次类文件吗?或者 - Tomcat 是否按 Web 应用程序缓存类?
提前感谢丹尼
答案1
答案取决于您的 web 应用程序所使用的类文件的位置。
如果您将给定的类放入 Tomcat 通用类加载器路径 $CATALINA_HOME/lib 中,它将可供所有 webapps 使用。其缓存形式也是如此。
如果您使用 Tomcat Web 应用程序类加载器路径 webapps/网络应用/WEB-INF/classes 和 webapps/网络应用/WEB-INF/lib 类和相应的类缓存在应用程序之间是隔离的。
技术背景
Tomcat 不符合 Java 本机处理类的方式,而是使用自定义 Java 类加载器。这是为了强制执行与以下相关的许多功能:
- Web 应用程序内的类处理
- 每个 Web 应用程序的类缓存
- 在 Web 应用程序启动/运行时预加载和重新加载类
- 类加载/引用的安全性
Tomcat 自定义类加载器使用 Java 默认的 Bootstrap、Extension 和 System 类加载器,但将 System 类加载器使用的 classpath 变量替换为其自己的类路径。这会产生以下效果:
- 用 Tomcat 自己的机制取代 Java 附带的认可标准覆盖机制。
在 Java 类加载层次结构的末尾添加两个额外的类加载器:
- Tomcat 通用类加载器
- 每个 Web 应用有单独的类加载器
Tomcat 忽略了原始类路径。
一个关键细节是,Web 应用程序类加载器不会先将类加载委托给其父类,而是尝试在请求时加载每个类。每个加载的类随后都会由相关的 Web 应用程序类加载器缓存。此类加载器/缓存级别不能在 Web 应用程序之间共享。
通用类加载器加载的所有类均可供所有 Web 应用程序(包括缓存)公开使用。不建议在通用类加载器路径中大量放置类,因为这样做:
- 破坏了可移植性
- Tomcat 和不同的 webapps 之间对类版本的要求可能不同。
- 维护成为一个问题,哪个类属于什么?
类加载/缓存/重新加载过程有很多细节。如果这些细节很重要,我建议你阅读专业 Apache Tomcat 6。
有人在这页。