远程对象

远程对象是啥

继承了UnicastRemoteObject的对象都可称为远程对象

让一个对象继承UnicastRemoteObject的能力,就是把自己发布出去。

UnicastRemoteObject初始化

构造方法

调用exportObject。

/**
* Creates and exports a new UnicastRemoteObject object using the
* particular supplied port.
*
* <p>The object is exported with a server socket
* created using the {@link RMISocketFactory} class.
*
* @param port the port number on which the remote object receives calls
* (if <code>port</code> is zero, an anonymous port is chosen)
* @throws RemoteException if failed to export object
* @since 1.2
*/
protected UnicastRemoteObject(int port) throws RemoteException
{
this.port = port;
exportObject((Remote) this, port);
}

java.rmi.server.UnicastRemoteObject#exportObject(java.rmi.Remote, int)

目的是接受remote call

/**
* Exports the remote object to make it available to receive incoming
* calls, using the particular supplied port.
*
* <p>The object is exported with a server socket
* created using the {@link RMISocketFactory} class.
*
* @param obj the remote object to be exported
* @param port the port to export the object on
* @return remote object stub
* @exception RemoteException if export fails
* @since 1.2
*/
public static Remote exportObject(Remote obj, int port)
throws RemoteException
{
return exportObject(obj, new UnicastServerRef(port));
}

查看一下sun.rmi.server.UnicastServerRef#UnicastServerRef(int)

public class UnicastServerRef extends UnicastRef implements ServerRef, Dispatcher {

这里调用的构造方法

public UnicastServerRef(int var1) {
super(new LiveRef(var1));
this.forceStubUse = false;
this.hashToMethod_Map = null;
this.methodCallIDCount = new AtomicInteger(0);
this.filter = null;
}

查看一下super方法

this.ref

public UnicastRef(LiveRef var1) {
this.ref = var1;
}

new LiveRef方法最终会调用。var1为new ObjID()。var2为TCPEndpoint.getLocalEndpoint(port),类型为TCPEndpoint。var3为true

    public LiveRef(ObjID var1, Endpoint var2, boolean var3) {
this.ep = var2;
this.id = var1;
this.isLocal = var3;
}

getLocalEndpoint

查看一下

public static TCPEndpoint getLocalEndpoint(int var0) {
return getLocalEndpoint(var0, (RMIClientSocketFactory)null, (RMIServerSocketFactory)null);
} public static TCPEndpoint getLocalEndpoint(int var0, RMIClientSocketFactory var1, RMIServerSocketFactory var2) {
TCPEndpoint var3 = null;
synchronized(localEndpoints) {
//只有var0为port,传入有值,其他均为null
TCPEndpoint var5 = new TCPEndpoint((String)null, var0, var1, var2);
//localEndpoints存放的是TCPEndpoint
LinkedList var6 = (LinkedList)localEndpoints.get(var5);
//是否配置了java.rmi.server.hostname
//重新采样主机host
String var7 = resampleLocalHost();
//如果不存在TCPEndpoint,这里重写了equals方法。吐槽一下这个equals方法,垃圾。
if (var6 == null) {
//host,port,null,null
var3 = new TCPEndpoint(var7, var0, var1, var2);
var6 = new LinkedList();
var6.add(var3);
var3.listenPort = var0;
//transport保存自身,这不来个循环引用?
var3.transport = new TCPTransport(var6);
//key为TCPEndpoint,value为TCPTransport
localEndpoints.put(var5, var6);
if (TCPTransport.tcpLog.isLoggable(Log.BRIEF)) {
TCPTransport.tcpLog.log(Log.BRIEF, "created local endpoint for socket factory " + var2 + " on port " + var0);
}
} else {
//如果get到了
synchronized(var6) {
var3 = (TCPEndpoint)var6.getLast();
String var9 = var3.host;
int var10 = var3.port;
TCPTransport var11 = var3.transport;
//如果host变了,就重新创建TCPEndpoint,把这个放到链表的末尾
if (var7 != null && !var7.equals(var9)) {
if (var10 != 0) {
var6.clear();
} var3 = new TCPEndpoint(var7, var10, var1, var2);
var3.listenPort = var0;
var3.transport = var11;
var6.add(var3);
}
}
} return var3;
}
}

sun.rmi.transport.tcp.TCPEndpoint构造方法

public TCPEndpoint(String var1, int var2, RMIClientSocketFactory var3, RMIServerSocketFactory var4) {
this.listenPort = -1;
this.transport = null;
if (var1 == null) {
var1 = "";
} this.host = var1;
this.port = var2;
this.csf = var3;
this.ssf = var4;
}

java.rmi.server.UnicastRemoteObject#exportObject(java.rmi.Remote, sun.rmi.server.UnicastServerRef)

这里是在sref上暴露remoteObject。这个remoteObject就是我们的远程对象。

/**
* Exports the specified object using the specified server ref.
*/
private static Remote exportObject(Remote obj, UnicastServerRef sref)
throws RemoteException
{
// if obj extends UnicastRemoteObject, set its ref.
if (obj instanceof UnicastRemoteObject) {
((UnicastRemoteObject) obj).ref = sref;
}
return sref.exportObject(obj, null, false);
}

sun.rmi.server.UnicastServerRef#exportObject(java.rmi.Remote, java.lang.Object, boolean)

看看如何创建代理对象的。

public Remote exportObject(Remote var1, Object var2, boolean var3) throws RemoteException {
Class var4 = var1.getClass(); Remote var5;
try {
//var5为远程对象的代理对象,Target里装入的也是代理对象
//var4为远程对象的class
//getClientRef返回new UnicastRef(this.ref)
//forceStubUse在构造方法里初始化为false
var5 = Util.createProxy(var4, this.getClientRef(), this.forceStubUse);
} catch (IllegalArgumentException var7) {
throw new ExportException("remote object implements illegal remote interface", var7);
}
//判断var5是否为RemoteStub
if (var5 instanceof RemoteStub) {
this.setSkeleton(var1);
}
//UnicastServerRef对象的this指针,为disp
//动态代理类为stub
//var3为false
Target var6 = new Target(var1, this, var5, this.ref.getObjID(), var3);
//暴露出去代理对象
//调用this.ep.exportObject(var1)。ep就是上面创建的TCPEndPoint
//进入TCPEndPoint,调用this.transport.exportObject(var1)
//创建listen,这里包含socket,以及socket的处理逻辑。exportCount++。
//target设置 setExportedTransport,为this
//ObjectTable存入target。objTable存入getObjectEndpoint->target。implTable存入getWeakImpl->target。
//getObjectEndpoint为new ObjectEndpoint(this.id, this.exportedTransport)。id就是ObjID,this.exportedTransport就是this。
//getWeakImpl返回WeakRef,在构造方法里可以看到,为WeakRef(var1, ObjectTable.reapQueue),var1为remote,就是我们实现的远程对象。
this.ref.exportObject(var6); //hashToMethod_Maps类型为 WeakClassHashMap<Map<Long, Method>>
//get不到会把var4 put进去。
this.hashToMethod_Map = (Map)hashToMethod_Maps.get(var4);
return var5;
}

sun.rmi.transport.Target#Target

暴露的target类的构造方法

public Target(Remote var1, Dispatcher var2, Remote var3, ObjID var4, boolean var5) {
this.weakImpl = new WeakRef(var1, ObjectTable.reapQueue);
this.disp = var2;
this.stub = var3;
this.id = var4;
this.acc = AccessController.getContext();
ClassLoader var6 = Thread.currentThread().getContextClassLoader();
ClassLoader var7 = var1.getClass().getClassLoader();
//如果var6的祖先加载器有var7
if (checkLoaderAncestry(var6, var7)) {
this.ccl = var6;
} else {
this.ccl = var7;
}
//false,不是永久的
this.permanent = var5;
if (var5) {
this.pinImpl();
} }

sun.rmi.server.Util#createProxy

public static Remote createProxy(Class<?> var0, RemoteRef var1, boolean var2) throws StubNotFoundException {
Class var3;
try {
//如果var0实现了Remote接口,那么直接返回var0,否则返回实现了Remote接口的超类,否则报错。
var3 = getRemoteClass(var0);
} catch (ClassNotFoundException var9) {
throw new StubNotFoundException("object does not implement a remote interface: " + var0.getName());
}
//var2为false
//ignoreStubClasses在静态块里取值为java.rmi.server.ignoreStubClasses
//withoutStubs类型为Map<Class<?>, Void>,在静态块里取值为Collections.synchronizedMap(new WeakHashMap(11)
//如果withoutStubs不包含var3,那么就尝试加载var3.getName+"_Stub"这个类,加载成功返回true,否则存入withoutStubs,返回false
//withoutStubs包含var3直接返回false
//所以如果是远程对象,不走这条。这里将逻辑杂糅,不太好。
if (var2 || !ignoreStubClasses && stubClassExists(var3)) {
return createStub(var3, var1);
} else {
//远程对象代理。
final ClassLoader var4 = var0.getClassLoader();
//只代理实现了remote的类或接口,要代理的类,这些类的方法都会被代理
final Class[] var5 = getRemoteInterfaces(var0);
//var1为UnicastRef。remote ref
//代理类。继承RemoteObject,实现InvocationHandler
final RemoteObjectInvocationHandler var6 = new RemoteObjectInvocationHandler(var1); try {
return (Remote)AccessController.doPrivileged(new PrivilegedAction<Remote>() {
public Remote run() {
//动态代理的典型使用
//会调用ref.invoke接口。UnicastRef.invoke方法
return (Remote)Proxy.newProxyInstance(var4, var5, var6);
}
});
} catch (IllegalArgumentException var8) {
throw new StubNotFoundException("unable to create proxy", var8);
}
}
}

sun.rmi.server.UnicastRef#invoke(java.rmi.Remote, java.lang.reflect.Method, java.lang.Object[], long)

//var1为远程对象
//var3为参数
//var4为getMethodHash(method))
public Object invoke(Remote var1, Method var2, Object[] var3, long var4) throws Exception {
if (clientRefLog.isLoggable(Log.VERBOSE)) {
clientRefLog.log(Log.VERBOSE, "method: " + var2);
} if (clientCallLog.isLoggable(Log.VERBOSE)) {
this.logClientCall(var1, var2);
}
//TCPChannel:this.ep.newSocket()
Connection var6 = this.ref.getChannel().newConnection();
StreamRemoteCall var7 = null;
boolean var8 = true;
boolean var9 = false; Object var13;
try {
if (clientRefLog.isLoggable(Log.VERBOSE)) {
clientRefLog.log(Log.VERBOSE, "opnum = " + var4);
}
//向var6里输出80
//使用ObjectOutput输出8字节objNum,再输出space,4字节unique,8字节time,2字节count
//再输出4字节-1,8字节getMethodHash(method))
var7 = new StreamRemoteCall(var6, this.ref.getObjID(), -1, var4); Object var11;
try {
ObjectOutput var10 = var7.getOutputStream();
this.marshalCustomCallData(var10);
//参数类型
var11 = var2.getParameterTypes(); for(int var12 = 0; var12 < ((Object[])var11).length; ++var12) {
//参数类型,参数值,输出流
//向var10里输出序列化的参数
marshalValue((Class)((Object[])var11)[var12], var3[var12], var10);
}
} catch (IOException var39) {
clientRefLog.log(Log.BRIEF, "IOException marshalling arguments: ", var39);
throw new MarshalException("error marshalling arguments", var39);
}
//这个查看一下
var7.executeCall(); try {
Class var46 = var2.getReturnType();
if (var46 == Void.TYPE) {
var11 = null;
return var11;
}
//从输入流里获取返回值
var11 = var7.getInputStream();
Object var47 = unmarshalValue(var46, (ObjectInput)var11);
var9 = true;
clientRefLog.log(Log.BRIEF, "free connection (reuse = true)");
this.ref.getChannel().free(var6, true);
var13 = var47;
} catch (ClassNotFoundException | IOException var40) {
((StreamRemoteCall)var7).discardPendingRefs();
clientRefLog.log(Log.BRIEF, var40.getClass().getName() + " unmarshalling return: ", var40);
throw new UnmarshalException("error unmarshalling return", var40);
} finally {
try {
var7.done();
} catch (IOException var38) {
var8 = false;
} }
} catch (RuntimeException var42) {
if (var7 == null || ((StreamRemoteCall)var7).getServerException() != var42) {
var8 = false;
} throw var42;
} catch (RemoteException var43) {
var8 = false;
throw var43;
} catch (Error var44) {
var8 = false;
throw var44;
} finally {
if (!var9) {
if (clientRefLog.isLoggable(Log.BRIEF)) {
clientRefLog.log(Log.BRIEF, "free connection (reuse = " + var8 + ")");
} this.ref.getChannel().free(var6, var8);
} } return var13;
}

sun.rmi.transport.StreamRemoteCall#executeCall

public void executeCall() throws Exception {
DGCAckHandler var2 = null; byte var1;
try {
if (this.out != null) {
var2 = this.out.getDGCAckHandler();
} this.releaseOutputStream();
DataInputStream var3 = new DataInputStream(this.conn.getInputStream());
//读1个字节
byte var4 = var3.readByte();
if (var4 != 81) {
if (Transport.transportLog.isLoggable(Log.BRIEF)) {
Transport.transportLog.log(Log.BRIEF, "transport return code invalid: " + var4);
} throw new UnmarshalException("Transport return code invalid");
} this.getInputStream();
//再读1个字节
var1 = this.in.readByte();
//读objID
this.in.readID();
} catch (UnmarshalException var11) {
throw var11;
} catch (IOException var12) {
throw new UnmarshalException("Error unmarshaling return header", var12);
} finally {
if (var2 != null) {
var2.release();
} }
//判断是否有报错
switch (var1) {
case 1:
return;
case 2:
Object var14;
try {
//读一个对象
var14 = this.in.readObject();
} catch (Exception var10) {
this.discardPendingRefs();
throw new UnmarshalException("Error unmarshaling return", var10);
} if (!(var14 instanceof Exception)) {
this.discardPendingRefs();
throw new UnmarshalException("Return type not Exception");
} else {
this.exceptionReceivedFromServer((Exception)var14);
}
default:
if (Transport.transportLog.isLoggable(Log.BRIEF)) {
Transport.transportLog.log(Log.BRIEF, "return code invalid: " + var1);
} throw new UnmarshalException("Return code invalid");
}
}

sun.rmi.transport.tcp.TCPTransport#listen

此处起了一个线程用来监听socket,处理远程请求。

private void listen() throws RemoteException {
assert Thread.holdsLock(this); TCPEndpoint var1 = this.getEndpoint();
int var2 = var1.getPort();
if (this.server == null) {
if (tcpLog.isLoggable(Log.BRIEF)) {
tcpLog.log(Log.BRIEF, "(port " + var2 + ") create server socket");
} try {
//server的实现是调用 sun.rmi.transport.proxy.RMIMasterSocketFactory,最终创建ServerSocket
this.server = var1.newServerSocket();
//此处用的是多线程阻塞I/O的方式
//AcceptLoop的run方法就是调用sun.rmi.transport.tcp.TCPTransport.AcceptLoop#executeAcceptLoop
Thread var3 = (Thread)AccessController.doPrivileged(new NewThreadAction(new AcceptLoop(this.server), "TCP Accept-" + var2, true));
var3.start();
} catch (BindException var4) {
throw new ExportException("Port already in use: " + var2, var4);
} catch (IOException var5) {
throw new ExportException("Listen failed on port: " + var2, var5);
}
} else {
SecurityManager var6 = System.getSecurityManager();
if (var6 != null) {
var6.checkListen(var2);
}
} }

sun.rmi.transport.tcp.TCPTransport.AcceptLoop#executeAcceptLoop

注意到使用ExecutorService,查看初始化,注意到

1、如果没有设置sun.rmi.transport.tcp.maxConnectionThreads参数,最大线程数可为Int的最大值。

2、在其中执行的线程有特权。

3、放到ExecutorService里的run方法最后会调用ConnectionHandler.run0。这里是处理远程调用的真正地方。

private void executeAcceptLoop() {
if (TCPTransport.tcpLog.isLoggable(Log.BRIEF)) {
TCPTransport.tcpLog.log(Log.BRIEF, "listening on port " + TCPTransport.this.getEndpoint().getPort());
} while(true) {
Socket var1 = null; try {
var1 = this.serverSocket.accept();
InetAddress var16 = var1.getInetAddress();
String var3 = var16 != null ? var16.getHostAddress() : "0.0.0.0"; try {
//var1为建立好连接的socket,var3为ip。
TCPTransport.connectionThreadPool.execute(TCPTransport.this.new ConnectionHandler(var1, var3));
} catch (RejectedExecutionException var11) {
TCPTransport.closeSocket(var1);
TCPTransport.tcpLog.log(Log.BRIEF, "rejected connection from " + var3);
}
} catch (Throwable var15) {
Throwable var2 = var15; try {
if (this.serverSocket.isClosed()) {
return;
} try {
if (TCPTransport.tcpLog.isLoggable(Level.WARNING)) {
TCPTransport.tcpLog.log(Level.WARNING, "accept loop for " + this.serverSocket + " throws", var2);
}
} catch (Throwable var13) {
}
} finally {
if (var1 != null) {
TCPTransport.closeSocket(var1);
} } if (!(var15 instanceof SecurityException)) {
try {
TCPEndpoint.shedConnectionCaches();
} catch (Throwable var12) {
}
} if (!(var15 instanceof Exception) && !(var15 instanceof OutOfMemoryError) && !(var15 instanceof NoClassDefFoundError)) {
if (var15 instanceof Error) {
throw (Error)var15;
} throw new UndeclaredThrowableException(var15);
} if (!this.continueAfterAcceptFailure(var15)) {
return;
}
}
}
}

UnicastRemoteObject执行逻辑

sun.rmi.transport.tcp.TCPTransport.ConnectionHandler#run0

    private void run0() {
TCPEndpoint var1 = TCPTransport.this.getEndpoint();
int var2 = var1.getPort();
TCPTransport.threadConnectionHandler.set(this); try {
this.socket.setTcpNoDelay(true);
} catch (Exception var31) {
} try {
if (TCPTransport.connectionReadTimeout > 0) {
this.socket.setSoTimeout(TCPTransport.connectionReadTimeout);
}
} catch (Exception var30) {
}
try {
//获取socket的输入流,返回SocketInputStream
InputStream var3 = this.socket.getInputStream();
//markSupported 判断该输入流能支持mark 和 reset 方法。
Object var4 = var3.markSupported() ? var3 : new BufferedInputStream(var3);
//这里为啥首先缓冲4个字节?
((InputStream) var4).mark(4);
//装饰成DataInputStream
DataInputStream var5 = new DataInputStream((InputStream) var4);
//读4个字节
int var6 = var5.readInt();
//16进制转字符为POST
if (var6 == 1347375956) {
if (TCPTransport.disableIncomingHttp) {
throw new RemoteException("RMI over HTTP is disabled");
} TCPTransport.tcpLog.log(Log.BRIEF, "decoding HTTP-wrapped call");
((InputStream) var4).reset(); try {
this.socket = new HttpReceiveSocket(this.socket, (InputStream) var4, (OutputStream) null);
this.remoteHost = "0.0.0.0";
var3 = this.socket.getInputStream();
var4 = new BufferedInputStream(var3);
var5 = new DataInputStream((InputStream) var4);
var6 = var5.readInt();
} catch (IOException var29) {
throw new RemoteException("Error HTTP-unwrapping call", var29);
}
}
//读2个字节
short var7 = var5.readShort();
//16进制转字符为JRMP
if (var6 == 1246907721 && var7 == 2) {
OutputStream var8 = this.socket.getOutputStream();
BufferedOutputStream var9 = new BufferedOutputStream(var8);
//var10为输出流
DataOutputStream var10 = new DataOutputStream(var9);
int var11 = this.socket.getPort();
if (TCPTransport.tcpLog.isLoggable(Log.BRIEF)) {
TCPTransport.tcpLog.log(Log.BRIEF, "accepted socket from [" + this.remoteHost + ":" + var11 + "]");
}
//读1个字节
byte var15 = var5.readByte();
TCPEndpoint var12;
TCPChannel var13;
TCPConnection var14;
switch (var15) {
case 75:
//回写78
var10.writeByte(78);
if (TCPTransport.tcpLog.isLoggable(Log.VERBOSE)) {
TCPTransport.tcpLog.log(Log.VERBOSE, "(port " + var2 + ") suggesting " + this.remoteHost + ":" + var11);
}
//回写主机host
var10.writeUTF(this.remoteHost);
//回写主机port
var10.writeInt(var11);
//输出
var10.flush();
//readUTF,先读两个字节表示utf的len,然后读取utf_len,然后将byte转int,
String var16 = var5.readUTF();
//读4个字节
int var17 = var5.readInt();
if (TCPTransport.tcpLog.isLoggable(Log.VERBOSE)) {
TCPTransport.tcpLog.log(Log.VERBOSE, "(port " + var2 + ") client using " + var16 + ":" + var17);
}
var12 = new TCPEndpoint(this.remoteHost, this.socket.getLocalPort(), var1.getClientSocketFactory(), var1.getServerSocketFactory());
var13 = new TCPChannel(TCPTransport.this, var12);
//var4,var9分别为this.socket的input,output,作为TCPConnection的input、output
var14 = new TCPConnection(var13, this.socket, (InputStream) var4, var9);
//读一个字节,转为int,分别判断80,81,82,83,84,后续对此方法做详细分析
//类名.this一般用于内部类调用外部类的对象时使用
TCPTransport.this.handleMessages(var14, true);
return;
case 76:
//对比75少了回写远程主机信息
var12 = new TCPEndpoint(this.remoteHost, this.socket.getLocalPort(), var1.getClientSocketFactory(), var1.getServerSocketFactory());
var13 = new TCPChannel(TCPTransport.this, var12);
var14 = new TCPConnection(var13, this.socket, (InputStream) var4, var9);
TCPTransport.this.handleMessages(var14, false);
return;
case 77:
//回写主机信息
if (TCPTransport.tcpLog.isLoggable(Log.VERBOSE)) {
TCPTransport.tcpLog.log(Log.VERBOSE, "(port " + var2 + ") accepting multiplex protocol");
} var10.writeByte(78);
if (TCPTransport.tcpLog.isLoggable(Log.VERBOSE)) {
TCPTransport.tcpLog.log(Log.VERBOSE, "(port " + var2 + ") suggesting " + this.remoteHost + ":" + var11);
} var10.writeUTF(this.remoteHost);
var10.writeInt(var11);
var10.flush();
var12 = new TCPEndpoint(var5.readUTF(), var5.readInt(), var1.getClientSocketFactory(), var1.getServerSocketFactory());
if (TCPTransport.tcpLog.isLoggable(Log.VERBOSE)) {
TCPTransport.tcpLog.log(Log.VERBOSE, "(port " + var2 + ") client using " + var12.getHost() + ":" + var12.getPort());
}
//这里是新增逻辑,多路复用,单独讲解。
ConnectionMultiplexer var18;
synchronized (TCPTransport.this.channelTable) {
var13 = TCPTransport.this.getChannel(var12);
//var4,var8是input、output作为ConnectionMultiplexer的input、output
var18 = new ConnectionMultiplexer(var13, (InputStream) var4, var8, false);
var13.useMultiplexer(var18);
} var18.run();
return;
default:
//只写一个79
var10.writeByte(79);
var10.flush();
return;
}
} TCPTransport.closeSocket(this.socket);
} catch (IOException var32) {
TCPTransport.tcpLog.log(Log.BRIEF, "terminated with exception:", var32);
return;
} finally {
TCPTransport.closeSocket(this.socket);
}
}

sun.rmi.transport.tcp.TCPTransport#handleMessages

    void handleMessages(Connection var1, boolean var2) {
int var3 = this.getEndpoint().getPort(); try {
DataInputStream var4 = new DataInputStream(var1.getInputStream());
//do while循环,如果var5不为break中的任意一个,是否可以造成dos攻击。
do {
//读一个字节
int var5 = var4.read();
if (var5 == -1) {
if (tcpLog.isLoggable(Log.BRIEF)) {
tcpLog.log(Log.BRIEF, "(port " + var3 + ") connection closed");
}
break;
} if (tcpLog.isLoggable(Log.BRIEF)) {
tcpLog.log(Log.BRIEF, "(port " + var3 + ") op = " + var5);
}
//判断
switch (var5) {
case 80:
StreamRemoteCall var6 = new StreamRemoteCall(var1);
if (!this.serviceCall(var6)) {
return;
}
break;
case 81:
case 83:
default:
throw new IOException("unknown transport op " + var5);
case 82:
DataOutputStream var7 = new DataOutputStream(var1.getOutputStream());
var7.writeByte(83);
var1.releaseOutputStream();
break;
case 84:
DGCAckHandler.received(UID.read(var4));
}
} while(var2);
} catch (IOException var17) {
if (tcpLog.isLoggable(Log.BRIEF)) {
tcpLog.log(Log.BRIEF, "(port " + var3 + ") exception: ", var17);
}
} finally {
try {
var1.close();
} catch (IOException var16) {
} } }

sun.rmi.transport.Transport#serviceCall

    public boolean serviceCall(final RemoteCall var1) {
try {
ObjID var39;
try {
//读8个字节作为num,再读4,8,2个字节new(unique, time, count)作为UID,取名space,然后new ObjID(num, space)
var39 = ObjID.read(var1.getInputStream());
} catch (IOException var33) {
throw new MarshalException("unable to read objID", var33);
}
//dgcID为静态变量,值为ObjID(2, new(0,0,0));
Transport var40 = var39.equals(dgcID) ? null : this;
//getTarget会从objTable取值。objTable为静态变量Hasp<ObjectEndpoint, Target>
//这个Target是远程对象的代理类
Target var5 = ObjectTable.getTarget(new ObjectEndpoint(var39, var40));
final Remote var37;
//var5.getImpl()从Target里的weakRef里取出Remote类,赋值给var37
if (var5 != null && (var37 = var5.getImpl()) != null) {
//从target里取出disp
final Dispatcher var6 = var5.getDispatcher();
//callCount++
var5.incrementCallCount(); boolean var8;
try {
transportLog.log(Log.VERBOSE, "call dispatcher");
//返回acc
final AccessControlContext var7 = var5.getAccessControlContext();
//返回ccl
ClassLoader var41 = var5.getContextClassLoader();
//获得线程上下文加载器
ClassLoader var9 = Thread.currentThread().getContextClassLoader(); try {
setContextClassLoader(var41);
currentTransport.set(this); try {
AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {
public Void run() throws IOException {
Transport.this.checkAcceptPermission(var7);
//在特权模块里执行dispatch,实现类为UnicastServerRef
//var37为var5里的remote
//var1为remotecall
//下面详细展开
var6.dispatch(var37, var1);
return null;
}
}, var7);
return true;
} catch (PrivilegedActionException var31) {
throw (IOException)var31.getException();
}
} finally {
setContextClassLoader(var9);
currentTransport.set((Object)null);
}
} catch (IOException var34) {
transportLog.log(Log.BRIEF, "exception thrown by dispatcher: ", var34);
var8 = false;
} finally {
var5.decrementCallCount();
} return var8;
} throw new NoSuchObjectException("no such object in table");
} catch (RemoteException var36) {
RemoteException var2 = var36;
if (UnicastServerRef.callLog.isLoggable(Log.BRIEF)) {
String var3 = ""; try {
var3 = "[" + RemoteServer.getClientHost() + "] ";
} catch (ServerNotActiveException var30) {
} String var4 = var3 + "exception: ";
UnicastServerRef.callLog.log(Log.BRIEF, var4, var36);
} try {
ObjectOutput var38 = var1.getResultStream(false);
UnicastServerRef.clearStackTraces(var2);
var38.writeObject(var2);
var1.releaseOutputStream();
} catch (IOException var29) {
transportLog.log(Log.BRIEF, "exception thrown marshalling exception: ", var29);
return false;
}
} return true;
}

sun.rmi.server.UnicastServerRef#dispatch

public void dispatch(Remote var1, RemoteCall var2) throws IOException {
try {
int var3;
ObjectInput var41;
try {
var41 = var2.getInputStream();
//读1个字节
var3 = var41.readInt();
} catch (Exception var38) {
throw new UnmarshalException("error unmarshalling call header", var38);
}
//调用远程对象,不会走这里
if (this.skel != null) {
this.oldDispatch(var1, var2, var3);
return;
} if (var3 >= 0) {
throw new UnmarshalException("skeleton class not found but required for client version");
} long var4;
try {
//读8个字节
var4 = var41.readLong();
} catch (Exception var37) {
throw new UnmarshalException("error unmarshalling call header", var37);
}
//输入流转化。MarshalInputStream
//Provides a MarshalInputStream that uses a caller provided ClassLoader to resolve classes during objects deserialization.
MarshalInputStream var7 = (MarshalInputStream)var41;
var7.skipDefaultResolveClass();
//回头看一下hashToMethod_Map
Method var42 = (Method)this.hashToMethod_Map.get(var4);
if (var42 == null) {
throw new UnmarshalException("unrecognized method hash: method not supported by remote object");
} this.logCall(var1, var42);
Object[] var9 = null; try {
//反序列化parameters
this.unmarshalCustomCallData(var41);
var9 = this.unmarshalParameters(var1, var42, var7);
} catch (AccessException var34) {
((StreamRemoteCall)var2).discardPendingRefs();
throw var34;
} catch (ClassNotFoundException | IOException var35) {
((StreamRemoteCall)var2).discardPendingRefs();
throw new UnmarshalException("error unmarshalling arguments", var35);
} finally {
var2.releaseInputStream();
} Object var10;
try {
//反射调用var1的var42方法,参数为var9。var10为返回值
var10 = var42.invoke(var1, var9);
} catch (InvocationTargetException var33) {
throw var33.getTargetException();
} try {
ObjectOutput var11 = var2.getResultStream(true);
Class var12 = var42.getReturnType();
if (var12 != Void.TYPE) {
//var12为返回值类型,将var10反序列化后,输出到var11
marshalValue(var12, var10, var11);
}
} catch (IOException var32) {
throw new MarshalException("error marshalling return", var32);
}
} catch (Throwable var39) {
Object var6 = var39;
this.logCallException(var39);
ObjectOutput var8 = var2.getResultStream(false);
if (var39 instanceof Error) {
var6 = new ServerError("Error occurred in server thread", (Error)var39);
} else if (var39 instanceof RemoteException) {
var6 = new ServerException("RemoteException occurred in server thread", (Exception)var39);
} if (suppressStackTraces) {
clearStackTraces((Throwable)var6);
} var8.writeObject(var6);
if (var39 instanceof AccessException) {
throw new IOException("Connection is not reusable", var39);
}
} finally {
var2.releaseInputStream();
var2.releaseOutputStream();
} }

总结

1、远程对象会被包装为一个代理对象,然后再封装为Target,然后发布出去。

2、这个代理对象只代理实现了remote接口的类。

3、发布的意思在TCPEndPoint上开启监听。等待逻辑处理。

直接给远程对象发送消息

import socket

ip_port = ('10.43.234.130', 10999)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) payload = b"%08x" % 1246907721 payload = payload + b"%04x" % 2
payload = payload + b"%02x" % 77 s.connect(ip_port)
s.send(bytes.fromhex(payload.decode('utf-8'))) rcv = s.recv(1024)
a = rcv[0:1] print(int.from_bytes(rcv[0:1], byteorder="little", signed=False))
# client的host长度
print(int(rcv[1:3].hex(), 16))
# client的host
print(rcv[3:-4].decode("utf-8"))
# client的port
print(int(rcv[-4:].hex(), 16))

返回值

死磕rmi之远程对象的更多相关文章

  1. 【死磕 Spring】----- IOC 之 获取 Document 对象

    原文出自:http://cmsblogs.com 在 XmlBeanDefinitionReader.doLoadDocument() 方法中做了两件事情,一是调用 getValidationMode ...

  2. RMI原理揭秘之远程对象

    讨论开始之前,我们先看看网上的一个例子,这个例子我腾抄了一分,没有用链接的方式,只是为了让大家看得方便,如有侵权,我立马***. 定义远程接口: 1 2 3 4 5 6 package com.guo ...

  3. 死磕Spring之AOP篇 - Spring AOP自动代理(三)创建代理对象

    该系列文章是本人在学习 Spring 的过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring 源码分析 GitHub 地址 进行阅读. Spring 版本:5.1 ...

  4. 死磕Spring之AOP篇 - Spring AOP两种代理对象的拦截处理

    该系列文章是本人在学习 Spring 的过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring 源码分析 GitHub 地址 进行阅读. Spring 版本:5.1 ...

  5. 死磕 java同步系列之redis分布式锁进化史

    问题 (1)redis如何实现分布式锁? (2)redis分布式锁有哪些优点? (3)redis分布式锁有哪些缺点? (4)redis实现分布式锁有没有现成的轮子可以使用? 简介 Redis(全称:R ...

  6. 死磕以太坊源码分析之p2p节点发现

    死磕以太坊源码分析之p2p节点发现 在阅读节点发现源码之前必须要理解kadmilia算法,可以参考:KAD算法详解. 节点发现概述 节点发现,使本地节点得知其他节点的信息,进而加入到p2p网络中. 以 ...

  7. 死磕以太坊源码分析之Fetcher同步

    死磕以太坊源码分析之Fetcher同步 Fetcher 功能概述 区块数据同步分为被动同步和主动同步: 被动同步是指本地节点收到其他节点的一些广播的消息,然后请求区块信息. 主动同步是指节点主动向其他 ...

  8. 死磕以太坊源码分析之downloader同步

    死磕以太坊源码分析之downloader同步 需要配合注释代码看:https://github.com/blockchainGuide/ 这篇文章篇幅较长,能看下去的是条汉子,建议收藏 希望读者在阅读 ...

  9. 死磕Spring之IoC篇 - 解析自定义标签(XML 文件)

    该系列文章是本人在学习 Spring 的过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring 源码分析 GitHub 地址 进行阅读 Spring 版本:5.1. ...

  10. 死磕Spring之IoC篇 - Bean 的创建过程

    该系列文章是本人在学习 Spring 的过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring 源码分析 GitHub 地址 进行阅读 Spring 版本:5.1. ...

随机推荐

  1. UVA439 Knight Moves

    原题Vjudge 题目大意 有一个骑士,他可以骑马日字型跳跃,问他从A点到B点最少要几步 解题思路 这题就是一个特别裸的广搜板子 它的主要问题在于输入输出 输入的数据我们可以用\(pair\)读入,第 ...

  2. 贪心算法Dijkstra

    Dijkstra 最短路径问题 : 给定一个带权有向图 G = (V, E, W),同时给定一个源点 u (u ∈ V),我们要找出从源点 u 出发到其它各点的最短路径距离,并得出这些最短路径的具体路 ...

  3. [python] 基于matplotlib_venn实现维恩图的绘制

    文章目录 VENN DIAGRAM(维恩图) 1. 具有2个分组的基本的维恩图 Venn diagram with 2 groups 2. 具有3个组的基本维恩图 Venn diagram with ...

  4. Redis缓存何以一枝独秀?——从百变应用场景与热门面试题中感受下Redis的核心特性与使用注意点

    大家好,又见面了. 本文是笔者作为掘金技术社区签约作者的身份输出的缓存专栏系列内容,将会通过系列专题,讲清楚缓存的方方面面.如果感兴趣,欢迎关注以获取后续更新. 作为<深入理解缓存原理与实战设计 ...

  5. python之路28 网络编程基础之OSI七层协议模型

    OSI七层协议 """ 七层模型,亦称OSI(Open System Interconnection).参考模型是国际标准化组织(ISO)制定的一个用于计算机或通信系统间 ...

  6. [WPF]xml序列化以及反序列化数据

    代码 XML序列化工具类 public static class XMLHelper { /// <summary> /// 将对象序列化为指定的文件名 /// </summary& ...

  7. Spring MVC的运行流程

    Spring MVC的运行流程 摘要:本文档主要结合官方给出的Spring MVC流程图结合一个简单的Spring MVC实例,分析并介绍了Spring MVC的运行流程. 目录 Spring MVC ...

  8. 算法学习笔记(8.1): 网络最大流算法 EK, Dinic, ISAP

    网络最大流 目录 网络最大流 EK 增广路算法 Dinic ISAP 作者有话说 前置知识以及更多芝士参考下述链接 网络流合集链接:网络流 最大流,值得是在不超过管道(边)容量的情况下从源点到汇点最多 ...

  9. P1162填涂颜色——题解

    题目描述 由数字0组成的方阵中,有一任意形状闭合圈,闭合圈由数字1构成,围圈时只走上下左右4个方向.现要求把闭合圈内的所有空间都填写成2.例如:6×6的方阵(n=6),涂色前和涂色后的方阵如下: 0 ...

  10. Linux c 程序自动启动自己

    在程序自动升级的时候需要自己重新启动自己 #include <stdio.h> #include <stdlib.h> #include <unistd.h> in ...