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

Java 21远程JMX调用传递java.time.Instant参数时触发InvalidClassException的解决方案咨询

Java 21远程JMX调用传递java.time.Instant参数时触发InvalidClassException的解决方案咨询

看起来你遇到的问题是Java 21下JMX远程调用传递java.time.Instant参数时触发序列化过滤拒绝的异常——明明返回Instant没问题,但传参就报错,这个情况我之前也碰到过,核心原因是JMX远程依赖的RMI在Java 9+有自己独立的序列化过滤规则,和你设置的全局jdk.serialFilter是完全分开的。

问题根源

Java 9及以后版本中,JMX的RMI连接器会忽略全局的jdk.serialFilter配置,转而使用专属的序列化过滤参数:

  • 服务端规则由jmx.remote.rmi.server.serial.filter.pattern控制
  • 客户端规则由jmx.remote.rmi.client.serial.filter.pattern控制
    你之前只设置了全局过滤,但JMX的RMI连接用了默认的严格规则,直接拒绝了java.time.Instant的序列化请求。

解决方案1:配置JMX专属序列化过滤参数

在服务端和客户端的JVM启动参数中分别添加对应的过滤规则,直接允许java.time.Instant的序列化:

服务端启动参数

-Djmx.remote.rmi.server.serial.filter.pattern=java.time.Instant;*

客户端启动参数

-Djmx.remote.rmi.client.serial.filter.pattern=java.time.Instant;*

测试环境可以直接用*允许所有类,但生产环境建议精确指定允许的类列表,避免安全风险。

解决方案2:临时Workaround(无需修改JVM参数)

如果暂时无法调整JVM启动参数,可以把Instant转换成序列化无限制的基本类型(比如毫秒时间戳)来传递,在服务端再转换回Instant:

修改客户端调用代码

// 把Instant转成毫秒时间戳
long instantMilli = Instant.now().toEpochMilli();
output = mbsc.invoke(on, "oper2", new Object[]{instantMilli}, new String[]{Long.class.getName()});

修改服务端MBean接口与实现

public interface JMXScriptMBean {
    Instant oper1();
    // 把参数类型改成Long
    void oper2(Long instMilli);
}

static class JMXScript implements JMXScriptMBean {
    @Override
    public Instant oper1() {
        return Instant.now();
    }

    @Override
    public void oper2(Long instMilli) {
        // 把时间戳转回Instant
        Instant inst = Instant.ofEpochMilli(instMilli);
        // 原来的业务逻辑
    }
}

额外验证点

确认你的服务端确实通过JVM参数启动了JMX远程RMI服务(比如启动时加了-Dcom.sun.management.jmxremote.port=9999等参数),因为你的服务端代码里没有显式创建RMI连接器的逻辑,完全依赖JVM默认的远程JMX配置。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.08 07:54:33