I'm using Java 21 and invoking remote JMX methods.
Calling a remote JMX method that returns a java.time.Instant
works fine.
However, when I try to invoke a method that takes an java.time.Instant
as a parameter, I get the following exception:
Exception in thread "main" java.io.InvalidClassException: filter status: REJECTED
at java.base/java.io.ObjectInputStream.filterCheck(ObjectInputStream.java:1439)
at java.base/java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:2071)
at java.base/java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1927)
at java.base/java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2252)
at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1762)
at java.base/java.io.ObjectInputStream.readArray(ObjectInputStream.java:2186)
at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1750)
at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:540)
at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:498)
at java.rmi/java.rmi.MarshalledObject.get(MarshalledObject.java:183)
at java.management.rmi/javax.management.remote.rmi.RMIConnectionImpl.unwrap(RMIConnectionImpl.java:1590)
at java.management.rmi/javax.management.remote.rmi.RMIConnectionImpl.unwrap(RMIConnectionImpl.java:1632)
at java.management.rmi/javax.management.remote.rmi.RMIConnectionImpl.invoke(RMIConnectionImpl.java:812)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
at java.base/java.lang.reflect.Method.invoke(Method.java:580)
at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:360)
at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:200)
at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:197)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:714)
at java.rmi/sun.rmi.transport.Transport.serviceCall(Transport.java:196)
at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:598)
at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:844)
at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:721)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:400)
at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:720)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
at java.base/java.lang.Thread.run(Thread.java:1583)
at java.rmi/sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(StreamRemoteCall.java:304)
at java.rmi/sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:280)
at java.rmi/sun.rmi.server.UnicastRef.invoke(UnicastRef.java:166)
at jdk.remoteref/jdk.jmx.remote.internal.rmi.PRef.invoke(Unknown Source)
at java.management.rmi/javax.management.remote.rmi.RMIConnectionImpl_Stub.invoke(RMIConnectionImpl_Stub.java:419)
at java.management.rmi/javax.management.remote.rmi.RMIConnector$RemoteMBeanServerConnection.invoke(RMIConnector.java:1020)
Both the client and the server are running the same JDK - jdk-21.0.7.
I tried launching both JVMs with -Djdk.serialFilter=*
but it made no difference.
server:
public class JMXServer {
public interface JMXScriptMBean {
Instant oper1();
void oper2(Instant inst);
}
static class JMXScript implements JMXScriptMBean {
@Override
public Instant oper1() {
return Instant.now();
}
@Override
public void oper2(Instant inst) {
}
}
public static void main(String[] args) throws Exception {
// Create and register the MBean
javax.management.MBeanServer mbs = java.lang.management.ManagementFactory.getPlatformMBeanServer();
JMXScriptMBean scriptBean = new JMXScript();
javax.management.ObjectName name = new javax.management.ObjectName("MDPubBeans:name=functionEnricher");
mbs.registerMBean(scriptBean, name);
System.out.println("JMXServer is running. Press Enter to exit...");
System.in.read();
}
}
client:
public static void main(String[] args) throws Exception
{
JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:9999/jmxrmi");
JMXConnector jmxc = JMXConnectorFactory.connect(url);
MBeanServerConnection mbsc = jmxc.getMBeanServerConnection();
ObjectName on = new ObjectName("MDPubBeans:name=functionEnricher");
Object output = mbsc.invoke(on, "oper1", new Object[0], new String[0]);
System.out.println(output);
output = mbsc.invoke(on, "oper2", new Object[]{Instant.now()}, new String[]{Instant.class.getName()});
System.out.println(output);
}
Is there a way to allow java.time.Instant
as a parameter for remote JMX calls in Java 21?
Any workaround or additional configuration needed?
JMX (open MBean) supports only a limited set of basic data types, and unfortunately, Instant
is not one of them. Looks like internally, the JMX serializer enforces this restriction using a hardcoded serialization filter, which blocks unsupported types like Instant
.
Proper way to pass Instant
is to wrap it in a CompositeData. Interestingly, Instant
did seem to work when returned directly as an operator return value. I'm not entirely sure why that is.