You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Docker容器中Java 11应用jstatd绑定RMI注册表失败求助

Docker容器内Java 11应用jstatd启动失败,无法连接VisualVM

我在本地Docker容器中运行Java 11应用,已在Dockerfile的CMD指令中添加以下JMX参数:

-Dcom.sun.management.jmxremote 
-Dcom.sun.management.jmxremote.port=1099 
-Dcom.sun.management.jmxremote.local.only=false 
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false

但在容器内执行jstatd命令时,出现绑定RMI注册表失败的错误,核心报错为java.io.InvalidClassException: filter status: REJECTED,完整错误输出如下:

/ # jstatd -J-Djava.rmi.server.logCalls=true -J-Djava.net.preferIPv4Stack=true -J-Djava.security.policy=jstatd.policy
Could not bind /JStatRemoteHost to RMI Registry
java.rmi.ServerException: RemoteException occurred in server thread; nested exception is: 
        java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is: 
        java.io.InvalidClassException: filter status: REJECTED
        at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(Unknown Source)
        at java.rmi/sun.rmi.transport.Transport$1.run(Unknown Source)
        at java.rmi/sun.rmi.transport.Transport$1.run(Unknown Source)
        at java.base/java.security.AccessController.doPrivileged(Native Method)
        at java.rmi/sun.rmi.transport.Transport.serviceCall(Unknown Source)
        at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(Unknown Source)
        at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(Unknown Source)
        at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(Unknown Source)
        at java.base/java.security.AccessController.doPrivileged(Native Method)
        at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(Unknown Source)
        at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
        at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
        at java.base/java.lang.Thread.run(Unknown Source)
        at java.rmi/sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(StreamRemoteCall.java:303)
        at java.rmi/sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:279)
        at java.rmi/sun.rmi.server.UnicastRef.invoke(UnicastRef.java:380)
        at java.rmi/sun.rmi.registry.RegistryImpl_Stub.rebind(RegistryImpl_Stub.java:158)
        at java.rmi/java.rmi.Naming.rebind(Naming.java:177)
        at jdk.jstatd/sun.tools.jstatd.Jstatd.bind(Jstatd.java:59)
        at jdk.jstatd/sun.tools.jstatd.Jstatd.main(Jstatd.java:145)
Caused by: java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is: 
        java.io.InvalidClassException: filter status: REJECTED
        at java.rmi/sun.rmi.registry.RegistryImpl_Skel.dispatch(Unknown Source)
        at java.rmi/sun.rmi.server.UnicastServerRef.oldDispatch(Unknown Source)
        at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(Unknown Source)
        at java.rmi/sun.rmi.transport.Transport$1.run(Unknown Source)
        at java.rmi/sun.rmi.transport.Transport$1.run(Unknown Source)
        at java.base/java.security.AccessController.doPrivileged(Native Method)
        at java.rmi/sun.rmi.transport.Transport.serviceCall(Unknown Source)
        at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(Unknown Source)
        at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(Unknown Source)
        at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(Unknown Source)
        at java.base/java.security.AccessController.doPrivileged(Native Method)
        at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(Unknown Source)
        at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
        at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
        at java.base/java.lang.Thread.run(Unknown Source)
Caused by: java.io.InvalidClassException: filter status: REJECTED
        at java.base/java.io.ObjectInputStream.filterCheck(Unknown Source)
        at java.base/java.io.ObjectInputStream.readNonProxyDesc(Unknown Source)
        at java.base/java.io.ObjectInputStream.readClassDesc(Unknown Source)

当前使用的jstatd策略文件内容:

/ # cat jstatd.policy 
grant codebase "jrt:/jdk.jstatd" {permission java.security.AllPermission;}; 
grant codebase "jrt:/jdk.internal.jvmstat" {permission java.security.AllPermission;};

解决方案

1. 关闭Java序列化过滤限制

Java 11默认启用了序列化过滤机制,会拦截jstatd的RMI通信类。启动jstatd时需添加参数允许所有类序列化:

-J-Djdk.serialFilter=*

完整启动命令:

jstatd -J-Djava.rmi.server.logCalls=true -J-Djava.net.preferIPv4Stack=true -J-Djava.security.policy=jstatd.policy -J-Djdk.serialFilter=*

2. 固定RMI端口并映射Docker端口

jstatd依赖RMI注册表端口和随机数据传输端口,为避免Docker端口映射问题,可显式指定两个端口:

  • 启动jstatd时添加端口参数(替换<宿主机IP>为实际IP):
jstatd -J-Djava.rmi.server.hostname=<宿主机IP> -J-Djava.rmi.registry.port=1099 -J-Djava.rmi.server.port=1100 -J-Djdk.serialFilter=* -J-Djava.security.policy=jstatd.policy
  • Docker运行容器时映射端口:
docker run -p 1099:1099 -p 1100:1100 <你的镜像名>

3. 确保策略文件可被正确读取

确认jstatd能访问到策略文件,可将文件放在固定路径(如/opt/jstatd.policy),启动时指定完整路径:

-J-Djava.security.policy=/opt/jstatd.policy

4. 直接通过JMX连接VisualVM(更简便)

若jstatd配置繁琐,可跳过jstatd,直接通过JMX连接:

  • 确保Docker已映射1099端口
  • 在VisualVM中选择「添加JMX连接」,输入地址宿主机IP:1099,无需认证(已关闭jmxremote.authenticate)

内容的提问来源于stack exchange,提问作者Manish

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 18:48:12