This discussion is archived
13 Replies Latest reply: Jan 21, 2012 3:43 PM by EJP RSS

Writing a custom RMI Activator process

746064 Newbie
Currently Being Moderated
Hello Group,

I am in the process of implementing a custom RMI activation scheme, in which remote Activatable objects will be hosted in a custom EXE process, instead of the standard Java.exe/Javaw.exe. I intend to use JNI to create the JVM in this custom EXE process and then load Java classes. I have used JNI to create JVMs in native processes before, but have no experience writing custom RMI activation systems.

Has anyone attempted this before, and knows if there are any gotchas that I should know early on?

Thanks,
Ranjit
  • 1. Re: Writing a custom RMI Activator process
    EJP Guru
    Currently Being Moderated
    Fairly tricky, but all you have to do is implement Activator, ActivationSystem etc., with all the correct semantics, which are all specified in the Javadoc and the RMI Specification. But I'm curious about this custom process. Maybe you should be using native methods instead.
  • 2. Re: Writing a custom RMI Activator process
    746064 Newbie
    Currently Being Moderated
    Thanks for your response. Can you please clarify what you meant by 'Maybe you should be using native methods'?

    I am beginning to see that this may not be as trivial as I initially thought it would be.

    Normally, when rmid launches child (java.exe) processes to host RMI servers, it pushes two pieces of information (ActivationID and ActivationGroupDesc) into the input stream of the newly forked child process and then runs the ActivationGroupInit class (via the command "java -classpath <> sun.rmi.server.ActivationGroupInit"). This class reads off the ActivationID and ActivationGroupDesc from the input stream and registers an activation group with the activation system. Seemingly, it then stays hung waiting for requests to activate an RMI server object when the need arises.

    With this knowledge under my belt, I thought to myself all that is happening under the covers is that a JVM is being loaded and a certain class is invoked which does all the magic thereafter. So I defined a Win32 EXE project, wrote some JNI code to load the JVM, and using JNI again, find the ActivationGroupInit class and run its main method. (Kinda what java.exe would do internally).

    Unfortunately, I am having problems with Activation and my EXE seems to be exiting. If I make it hang, I get a Marshaling exception. I have to look deeper at the source of the Java launcher and see if it does anything special for RMI. Unfortunately, I am unable to find samples that show how to write a custom activator.

    Ranjit
  • 3. Re: Writing a custom RMI Activator process
    EJP Guru
    Currently Being Moderated
    Can you please clarify what you meant by 'Maybe you should be using native methods'?
    I mean what I said. You are embedding the activated JVM in a custom exe, presumably because you have other code in there that you want executed: maybe you should be organizing to call that code from Java via JNI. Then you wouldn't need the custom exe, the custom activator, the custom activation system/group/monitor etc.

    (In fact you don't need those anyway. All you need is to create your ActivationGroupDesc with a cmdPath that points to your exe. The entire activation system can be used as is.)

    There are no samples almost certainly because there was no expectation that anyone else would want to implemenet activation, maybe except for JVM implementors. You are probably the first person ever to attempt another activator in the 14 years since it appeared. In fact the Activation system is rather poorly designed in that most of it should have been put into an SPI package. (It has other design problems too, specifically in the security area.)
  • 4. Re: Writing a custom RMI Activator process
    746064 Newbie
    Currently Being Moderated
    The requirement isn't that of running custom code in the RMI Server for which JNI could be considered, but that of renaming the RMI server process itself and change it from being java.exe/javaw.exe to a name that our customers are accustomed to. This is an overwhelming requirement at the moment. There are two ways that I am considering at the moment.

    1. Recompile java.c (the launcher code) into an EXE with a name of my choosing.
    2. Write a custom EXE, embed the JVM and bootstrap the RMI Activation machinery.

    1) may have licensing constraints, and I haven't fully grasped the implication of going down that path. For 2) I wrote the custom EXE, specified it in the ActivationGroupDesc (as you have suggested), etc but have been running into problems. I am now reading the spec more thoroughly to understand what might be going wrong.

    Ranjit
  • 5. Re: Writing a custom RMI Activator process
    EJP Guru
    Currently Being Moderated
    Your exe has to behave as though it was java.exe. All its arguments must be passed to the JVM that you create. Or else you could just copy java.exe to xxx.exe where xxx is anything you like, named in the cmdPath of the ActivationGroup of course.

    It's a very strange requirement. What does your customer care what things are called? What business it it of his? And do you realize that you won't get code sharing if you have multiple JVM-based exes?
  • 6. Re: Writing a custom RMI Activator process
    746064 Newbie
    Currently Being Moderated
    I have a breakthrough. I am able to host a simple RMI server inside a custom EXE. All I do is inside the main of a Win32 EXE, create the JVM and use JNI to call the ‘main’ of a Java class I wrote below.

    This class runs (some undocumented) code to bootstrap the RMI machinery. Hereafter my EXE process process remains alive and is available to service RMI requests. Using this approach, I wouldn’t need to recompile java.c inorder to rename it as long as my custom JNI code is able to parse in all the VM options passed in by RMID in order to create the JVM.

    I was missing the crucial step of calling back into rmid (the Activator) and registering the newly created group, only after which would rmid start creating instances of the remote object. Your advice that I carefully read the spec helped!

    public class Host {
    public static void main(String[] args) throws Exception {
    Class clsInputStream = Class.forName("sun.rmi.server.MarshalInputStream");
    Constructor ctor = clsInputStream.getConstructor(InputStream.class);
    Method readObj = clsInputStream.getMethod("readObject", null);
    Method readLong = clsInputStream.getMethod("readLong", null);

    // Instantiate MarshalInputStream
    Object in = ctor.newInstance(System.in);

    // Read all the data passed in by the Activator (rmid)
    ActivationGroupID id = (ActivationGroupID) readObj.invoke(in);
    ActivationGroupDesc desc = (ActivationGroupDesc) readObj.invoke(in);
    long incarnation = (Long) readLong.invoke(in);

    // Create the ActivationGroup
    ActivationGroup grp = ActivationGroup.createGroup(id, desc, incarnation);

    // Callback into rmid to register the group.
    ActivationGroup.getSystem().activeGroup(id, grp, incarnation);

    // rmid will now invoke ActivationGroup.newInstance to create the RMI server
    }
    }

    Thanks,
    Ranjit
  • 7. Re: Writing a custom RMI Activator process
    746064 Newbie
    Currently Being Moderated
    The customer doesn't want to see a whole bunch of java.exe processes in TaskManager, especially if they are a .Net shop. Until the previous release, we had a DCOM architecture involving native Win32 processes, the names of which are well known to our customers and part of their vocabulary in dealing with customer support, etc. DCOM is now being replaced with RMI and the change must be seamless and must not introduce new artifacts in the story telling.
  • 8. Re: Writing a custom RMI Activator process
    746064 Newbie
    Currently Being Moderated
    Spoke too soon :) Still some problems.
  • 9. Re: Writing a custom RMI Activator process
    EJP Guru
    Currently Being Moderated
    I have a breakthrough. I am able to host a simple RMI server inside a custom EXE. All I do is inside the main of a Win32 EXE, create the JVM and use JNI to call the ‘main’ of a Java class I wrote below.
    You don't need a custom exe. You don't need a Java class. You don't need any of this crud. See above. Just make a copy of java.exe, call it whatever you like, and name it in the cmdPath of your ActivationGroupDesc. That's it. Period.
  • 10. Re: Writing a custom RMI Activator process
    746064 Newbie
    Currently Being Moderated
    I considered making a copy of java.exe and renaming it but didn't pursue it fearing violation of licensing agreements.
  • 11. Re: Writing a custom RMI Activator process
    EJP Guru
    Currently Being Moderated
    Then you still don't need a Java class, and you don't need to do anything about the standard input. Just pass all the arguments you receive to the created JVM. You will receive the name of an activation group impl class that does all that for you.
  • 12. Re: Writing a custom RMI Activator process
    746064 Newbie
    Currently Being Moderated
    I tired making that approach work as well, but was running into exceptions. Somehow it seemed that the callback into rmid informing about the new group, wasn't happening. When I explicitly made the callback to register the newly created ActivationGroup it worked, for which I had to write my own Java program that. Am sure I was doing something incorrect in the first place, because the spec mentions that ActivationGroup.createGroup must also internally, callback into rmid to register the newly created group, so just invoking the main of the ActivationGroupInit would have been sufficient.
  • 13. Re: Writing a custom RMI Activator process
    EJP Guru
    Currently Being Moderated
    I don't see how it can possibly not work. Java.exe manages it without knowing an activation group from a hole in the ground. You must have done something wrong somewhere. Your exe doesn't have to do anything that java.exe doesn't do.

Legend

  • Correct Answers - 10 points
  • Helpful Answers - 5 points