RMI 里 stub 是什么?参数怎么传?远程对象什么时候被回收?服务器宕了客户端看到什么?这篇用服务器与客户端两个 JVM 逐项验证,并开启 JEP 290 反序列化过滤器看被拒绝的调用。
[服务器] 就绪;stub 的类:jdk.proxy1.$Proxy0;stub 实现的接口:[interface Hello];registry 端口 19099,对象端口 19100;pid 56219
服务器进程监听的 TCP 端口: ['19099', '19100']
1 lookup 得到的对象类:jdk.proxy1.$Proxy0;是 Proxy:true;greet:hello rmi from RMI TCP Connection(2)-127.0.0.1
registry.list():[hello]
2000 次 greet 的平均耗时 0.072 ms/次(本机回环) 2 addAll([1,2,3]) = 6
客户端的列表在服务器 mutate 之后:[1, 2, 3](没有变化:参数按值传递,服务器改的是序列化副本)
传 Remote 对象作参数:服务器通过 stub 回调了客户端(按引用),stub 类是 jdk.proxy1.$Proxy1
3 传一个不可序列化的 new Object():java.rmi.MarshalException: error marshalling arguments; nested exception is: ← 原因 java.io.NotSerializableException: java.lang.Object 4 fail(1) 客户端捕获:java.lang.IllegalStateException: 服务器端的 IllegalStateException
4 fail(2) 客户端捕获:java.io.FileNotFoundException: 服务器端的 FileNotFoundException
4 fail(3) 客户端捕获:java.lang.RuntimeException: 服务器端的未声明运行时异常
5 lookup 不存在的名字:java.rmi.NotBoundException: nope
服务器端的输出(第二节与第三节期间):
[服务器] mutate 之后服务器手里的列表:[1, 2, 3, 999]
[服务器] 回调客户端:客户端收到:来自服务器;cb 的类:jdk.proxy1.$Proxy1 6 服务器配置了 serialFilter 拒绝 ArrayList 后,传 ArrayList: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
传 LinkedList:37 客户端 lookup 并调用一次后,丢掉引用并 System.gc();时间戳 1791044712196 (a) 客户端丢掉 stub 并 System.gc():服务器 unreferenced() 距客户端丢掉引用 0.01 秒 7b 客户端调用一次后直接 Runtime.halt(不会发 clean 调用);时间戳 1791044720957 (b) 客户端不发 clean 直接 halt:服务器 unreferenced() 距客户端消失 3.01 秒(租约 3 秒)
hello 先调用一次 from RMI TCP Connection(2)-127.0.0.1
7 服务器被 kill -9 之后用旧 stub 调用:java.rmi.ConnectException: Connection refused to host: 127.0.0.1; nested exception is:
再 lookup:java.rmi.ConnectException: Connection refused to host: 127.0.0.1; nested exception is: