给Tomcat设置JDK启动参数

给Tomcat设置JDK启动参数

有的框架读取参数的方式是通过System.getProperty(key);读取参数,应用又是运行在Tomcat中的,那么如何给key设置参数呢?

推测

Tomcat也是Java写的,它的启动也应该是我们熟悉的方式,比如java -jar或者java -cp之类的启动方式。

Tomcat的启动脚本为catalina,那么启动的奥秘就在这个脚本里。

通过读Windows的启动脚本,也可以应用在Linux的启动脚本上,逻辑应该是一致的。

探索

Windows平台的Tomcat,脚本对应的后缀是bat,我们直接打开catalina.bat一探究竟。

JAVA_OPTS

可以先直接翻到脚本的末尾,可以看到如下内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
rem Execute Java with the applicable properties
if not "%JPDA%" == "" goto doJpda
if not "%SECURITY_POLICY_FILE%" == "" goto doSecurity
%_EXECJAVA% %CATALINA_LOGGING_CONFIG% %LOGGING_MANAGER% %JAVA_OPTS% %CATALINA_OPTS% %DEBUG_OPTS% -D%ENDORSED_PROP%="%JAVA_ENDORSED_DIRS%" -classpath "%CLASSPATH%" -Dcatalina.base="%CATALINA_BASE%" -Dcatalina.home="%CATALINA_HOME%" -Djava.io.tmpdir="%CATALINA_TMPDIR%" %MAINCLASS% %CMD_LINE_ARGS% %ACTION%
goto end
:doSecurity
%_EXECJAVA% %CATALINA_LOGGING_CONFIG% %LOGGING_MANAGER% %JAVA_OPTS% %CATALINA_OPTS% %DEBUG_OPTS% -D%ENDORSED_PROP%="%JAVA_ENDORSED_DIRS%" -classpath "%CLASSPATH%" -Djava.security.manager -Djava.security.policy=="%SECURITY_POLICY_FILE%" -Dcatalina.base="%CATALINA_BASE%" -Dcatalina.home="%CATALINA_HOME%" -Djava.io.tmpdir="%CATALINA_TMPDIR%" %MAINCLASS% %CMD_LINE_ARGS% %ACTION%
goto end
:doJpda
if not "%SECURITY_POLICY_FILE%" == "" goto doSecurityJpda
%_EXECJAVA% %CATALINA_LOGGING_CONFIG% %LOGGING_MANAGER% %JAVA_OPTS% %JPDA_OPTS% %CATALINA_OPTS% %DEBUG_OPTS% -D%ENDORSED_PROP%="%JAVA_ENDORSED_DIRS%" -classpath "%CLASSPATH%" -Dcatalina.base="%CATALINA_BASE%" -Dcatalina.home="%CATALINA_HOME%" -Djava.io.tmpdir="%CATALINA_TMPDIR%" %MAINCLASS% %CMD_LINE_ARGS% %ACTION%
goto end
:doSecurityJpda
%_EXECJAVA% %CATALINA_LOGGING_CONFIG% %LOGGING_MANAGER% %JAVA_OPTS% %JPDA_OPTS% %CATALINA_OPTS% %DEBUG_OPTS% -D%ENDORSED_PROP%="%JAVA_ENDORSED_DIRS%" -classpath "%CLASSPATH%" -Djava.security.manager -Djava.security.policy=="%SECURITY_POLICY_FILE%" -Dcatalina.base="%CATALINA_BASE%" -Dcatalina.home="%CATALINA_HOME%" -Djava.io.tmpdir="%CATALINA_TMPDIR%" %MAINCLASS% %CMD_LINE_ARGS% %ACTION%
goto end

:end

这里可以看到一个重要的变量名JAVA_OPTS,锁定它一路往上找,找到它最初是如何产生的,然后可以看到

1
2
3
4
5
6
7
8
if not "%JSSE_OPTS%" == "" goto gotJsseOpts
set "JSSE_OPTS=-Djdk.tls.ephemeralDHKeySize=2048"
:gotJsseOpts
set "JAVA_OPTS=%JAVA_OPTS% %JSSE_OPTS%"

rem Register custom URL handlers
rem Do this here so custom URL handles (specifically 'war:...') can be used in the security policy
set "JAVA_OPTS=%JAVA_OPTS% -Djava.protocol.handler.pkgs=org.apache.catalina.webresources"

这里可以看出来Tomcat这个家伙是直接读取系统环境变量来的,看到这里就已经有了解决办法,但是别急。

CATALINA_OPTS

再往上找,可以找到Tomcat留下的注释

1
2
3
4
5
6
rem   JAVA_OPTS       (Optional) Java runtime options used when any command
rem is executed.
rem Include here and not in CATALINA_OPTS all options, that
rem should be used by Tomcat and also by the stop process,
rem the version command etc.
rem Most options should go into CATALINA_OPTS.

Tomcat在注释里还说了大部分情况下应使用CATALINA_OPTS参数,可以我们还可以继续看Tomcat对于CATALINA_OPTS参数的注释说了什么

1
2
3
4
5
6
rem   CATALINA_OPTS   (Optional) Java runtime options used when the "start",
rem "run" or "debug" command is executed.
rem Include here and not in JAVA_OPTS all options, that should
rem only be used by Tomcat itself, not by the stop process,
rem the version command etc.
rem Examples are heap size, GC logging, JMX ports etc.

执行catalina脚本时附带run或者debug时应用CATALINA_OPTS参数,看到这里以为要结束的时候,但还有东西。

setenv

上方还有一个重要的注释

1
2
3
4
5
6
7
8
9
10
11
12
13
rem Environment Variable Prerequisites
rem
rem Do not set the variables in this script. Instead put them into a script
rem setenv.bat in CATALINA_BASE/bin to keep your customizations separate.
rem
rem WHEN RUNNING TOMCAT AS A WINDOWS SERVICE:
rem Note that the environment variables that affect the behavior of this
rem script will have no effect at all on Windows Services. As such, any
rem local customizations made in a CATALINA_BASE/bin/setenv.bat script
rem will also have no effect on Tomcat when launched as a Windows Service.
rem The configuration that controls Windows Services is stored in the Windows
rem Registry, and is most conveniently maintained using the "tomcat8w.exe"
rem maintenance utility.

…Tomcat告诉我们,不要在这个文件里定义自己的变量,而是要写在CATALINA_BASE/bin/setenv.bat的脚本中。

可以看到脚本中也有调用到setenv的代码

1
2
3
4
5
6
7
rem Get standard environment variables
if not exist "%CATALINA_BASE%\bin\setenv.bat" goto checkSetenvHome
call "%CATALINA_BASE%\bin\setenv.bat"
goto setenvDone
:checkSetenvHome
if exist "%CATALINA_HOME%\bin\setenv.bat" call "%CATALINA_HOME%\bin\setenv.bat"
:setenvDone

那么CATALINA_BASE的值是什么,再慢慢扒它

1
2
3
4
rem Copy CATALINA_BASE from CATALINA_HOME if not defined
if not "%CATALINA_BASE%" == "" goto gotBase
set "CATALINA_BASE=%CATALINA_HOME%"
:gotBase

这里可以看到如果没有定义CATALINA_BASE就会把CATALINA_HOME的值赋给它,那CATALINA_HOME的值呢?

1
2
3
4
5
6
7
8
9
rem Guess CATALINA_HOME if not defined
set "CURRENT_DIR=%cd%"
if not "%CATALINA_HOME%" == "" goto gotHome
set "CATALINA_HOME=%CURRENT_DIR%"
if exist "%CATALINA_HOME%\bin\catalina.bat" goto okHome
cd ..
set "CATALINA_HOME=%cd%"
cd "%CURRENT_DIR%"
:gotHome

可以看到,如果没有在系统变量中预设CATALINA_HOME的值的话,Tomcat将会把catalina.bat脚本所在目录上级目录的值赋值给它,所以CATALINA_HOME的值相当于Tomcat的目录,至此破案。

看到这里,也可以大概的推测IDEA它是怎么玩Tomcat的了,IDEA可以通过启动脚本前设置相关的变量来达到设置JDK等相关的参数。

解决

下面三种解决方案,均是以Windows为例,Linux同理只是shell有所不同。

创建setenv脚本

推荐用这种方式去解决,规范。通过上面的探索,我们可以创建CATALINA_BASE/bin/setenv.bat脚本来设置我们需要的CATALINA_OPTS变量,一般在Tomcat的bin目录下创建setenv脚本就好,如果有设置其他的变量如CATALINA_BASE、CATALINA_HOME还需要再做其他判断。

下面以Windows为例子,创建``setenv.bat`,内容如下

1
set CATALINA_OPTS=-Dkey=233

就完成了CATALINA_OPTS变量的赋值而影响到JDK的环境变量。

设置系统变量

这个方法不用创建脚本文件,但这个方法对IDEA不生效,IDEA这家伙应该是覆盖了CATALINA_OPTS变量,但如果是自己启动Tomcat的话是可以的。

注意shell有临时变量这个概念,shell会复制系统变量作为副本运行命令,这里分歧成两种方案。

临时变量

在同一个shell命令窗口内设置CATALINA_OPTS变量,然后启动tomcat。

1
2
3
# 在Tomcat的bin目录下set 
set CATALINA_OPTS=-Dkey=233
catalina.bat run

系统变量

先设置CATALINA_OPTS变量,只设置一次就行,以后都不用再设置了。

1
setx "CATALINA_OPTS" "-Dkey=233"

在Tomcat的bin目录下打开shell命令窗口执行

1
catalina.bat run 

设置脚本中的变量

直接修改Tomcat的bin目录下的catalina脚本代码,不推荐这样做。

想这样搞的话,改法五花八门,比如在脚本开头,就可以定义CATALINA_OPTS或JAVA_OPTS的值,具体做法就不举例了。


给Tomcat设置JDK启动参数
https://blog.gugu.dev/2024-02-21/给Tomcat设置JDK启动参数/
作者
MinMin
发布于
2024年2月21日
许可协议