本文讲解Tomcat的类加载器机制和遇到的一个项目问题及排查过程。

Tomcat的classloader

遇到的项目问题及排查过程

项目中需要动态编译类,所以用到了jdk中的tools.jar(见如何在代码中编译java类),此前项目一直用中间件服务的形式启动,启动脚本中指定了jdk,没有任何问题。后来将项目打成了war包放在原生tomcat中执行,出现了找不到tools.jar中类的错误。

排查过程如下:

  1. 查看启动日志,发现如下:
    1
    信息 [main] org.apache.catalina.startup.VersionLoggerListener.log Java Home:             /usr/local/java/jre

用的是JRE_HOME,只有运行时环境,当然就没有工具类了;

  1. 需要重新指定java home,于是依次查看 startup.sh->catalina.sh->setclasspath.sh,看到了如下解释:
    1
    2
    3
    4
    5
    6
    #   JAVA_HOME       Must point at your Java Development Kit installation.
    # Required to run the with the "debug" argument.
    #
    # JRE_HOME Must point at your Java Runtime installation.
    # Defaults to JAVA_HOME if empty. If JRE_HOME and JAVA_HOME
    # are both set, JRE_HOME is used.

当环境变量中JRE_HOME和JAVA_HOME都设置,且不是debug模式时,使用JRE_HOME。

从而发现问题所在。

  1. 在setclasspath.sh中将JRE_HOME显式指定为JAVA_HOME,JRE_HOME="$JAVA_HOME",天真的以为这样就可以,但是看启动日志,发现仍然使用的JAVA_HOME/jre,所以没有更好的方法了,只能将tools.jar放到工程中了。