I have a simple RMI 'compute' server application (similar to this) that accepts objects of some interface type from clients over RMI, executes the compute() method of the received object and returns the result over RMI to the remote client. The jobs are 'one-offs' and there is no interaction between the different jobs or between objects of different jobs.
I would like to be able to modify classes and submit instances to the compute server for execution without constantly restarting the server JVM. However when a class that has been modified is submitted again as a parameter to a remote call it's method behaviour does not change (this occurs with anonymous classes also). I have been reading up about serialization and I realise that this is to do with the ClassLoader being unable to modify existing classes.
From my reading on SO and elsewhere I realise that somehow the ClassLoader that loaded the stream class must be GC'd and replaced in order to load a new version of my class. I have an idea how to do this but the situation seems complicated by the underlying RMI runtime and it having its own RMIClassloader.
My question is: What would be the easiest way to load each new version of a class received via RMI parameters. Ideally I'm looking for a way to have each remote call get a new ClassLoader and to dispose of it upon return. Is this feasible to do without an intricate knowledge of customised ClassLoaders and the internals of RMI?
Any pointers to reading materials or examples welcome!
Edit: here is the compute server's remote interface:
public interface ComputationEngine extends Remote {
public Object execute(Task t) throws RemoteException;
}
and the 'compute job' interface, Task:
public interface Task extends java.io.Serializable {
public Object compute();
}
The only way to this is to have a new ClassLoader when you want to change a Class.
How about making use of the URLClassLoader and making the code available from a URL
I use it in one of my projects to update APIs when the jar file changes. Take a look here:
http://code.google.com/p/open-forum/source/browse/trunk/Wiki/org/one/stone/soup/wiki/jar/manager/JarManager.java
Line 184+
Check your emails :-)
This isn't really answering your question, but it might be possible to make changing part of your classes into data instead of the actual class. Use a Map instead of fields, etc. You'd have a lot fewer classes floating around, and your code would probably be simpler too.
Related
[Context]
I need to send data from one applet to another. In addition, one of the applets needs to be deleted and reinstalled. After the installation, data exchange between the applets needs to be possible.
Is Shareable Interface useful to realize that?
[Theoretical]
In general, I would like to know the cases where shareable interface is a good idea and What its principal use.
[Practice]
I took example from this answer but it does not work. I think I did not understand how to implement. I tried to create two applets in the same package, one master and one slave. But I got 6F 00 when slave is selected. I did other test with two packages. But I got same error.
Shareable allows you to exchange the data between applets on the card.
There are some limitations though, the main being the fact that one cannot freely exchange internal objects. Only objects allowed for sharing can pass via the Shared interface. The example you mention uses some proprietary “SharedArray” interface to implement this.
By default, only standard global objects such as APDU backing array, or various STK objects can be used for this purpose.
In addition, it is possible to pass simple value types such as byte and short via the Shared interface methods.
In some cases, especially in STK environments the Shared interface is used to initiate the operations while the data is passed via a separate EF on the card which is used as a “mailslot”.
Regarding, the implementation itself, one needs to remember that Shareable interface is just a marker and as such you need to define a concrete interface that inherits from Shareable to be able to use it in the application.
The above interface constitutes a hard dependency for any application using or implementing this interface.
As a result, the package containing the interface definition cannot be deleted if any of the other applets/libraries use it.
One of the common options is to define the interface in a separate library and install it first. Since it is not likely to change, and if it does you would change the AID,version anyway, all other clients can be freely installed and deleted.
Lastly, please keep in mind Sharable interface should be used with care due to security issues associate with data sharing.
I highly recommend getting a copy of “Java Card Technology for Smart Cards: Architecture and Programmer's Guide” which covers these topics and much more.
Answering your question in order
[Context]
Shareable interface is used when one applet(Client Applet) need to access methods from another applet(Server applet) provided both the applets are located in different packages.Applets in different packages are separated by a firewall to prevent access to applet data across package.
Applet instances can be deleted in any order but Applet package should deleted in order. That is, first client package is deleted than server package is deleted.
[Theoretical]
Shareable interface is useful for object sharing since firewall restrict object sharing between packages.
For proper uses cases kindly go through this white paper - www.usenix.org/legacy/event/smartcard99/full_papers/montgomery/montgomery.pdf
[Practice]
Kindly check solution for shareable interface implementation - https://stackoverflow.com/a/57200926/4752262
I am using a Java library, with two classes Foo and FooConfig; I am unable to change the library code, but can read it. Here are the relevant functions of a Foo:
public class Foo
{
/** Install a configuration on this Foo */
void configure(FooConfig config);
/** Uninstall the current configuration */
void unconfigure();
}
The library creates Foos at times I can't control, and installs configurations shortly after creation. A Foo can only have on configuration at a time. I would like to use MyFooConfig, inherited from FooConfig, instead. Is there any way to intercept the configure call, or the FooConfig constructor, or anything like that to use my class instead?
My current solution is to get a reference to the Foo object shortly after its creation and configuration, uninstall the current configuration,and then install a MyFooConfig instead. This could work, but it causes several different problems (both with being a difficult solution to implement and with some inelegancies which can't be hidden from the user). Is there a better way, preferably using features of Java to intercept the constructor call to FooConfig, or the configure method, or something similar? The closest thing to an alternate solution I've found is to try to use a different ClassLoader to replace FooConfig with my own class behind the scenes, but I don't actually have access to the object that creates the FooConfigs so I don't think that's possible. Other things that looked promising but ultimately didn't pan out are proxy objects (I can't make the Foos be proxy objects), seeing if I could somehow get notified when a FooConfig was created without actually intercepting the constructor (so I could find its Foo and reconfigure it in a better way than I`m currently doing), and changing the library code itself (which, for various reasons, turns out to not be possible).
I don't know much about aspect-oriented programming, but it seems like it could help. Unfortunately, all the AOP Java tools seem to require special compilers, and I don't want to change the build process.
Here's my situation:
I have a server application, providing a remote interface which uses bean objects as call parameters / return values. These are of course Serializable. For instance, a Doctor, that works in a Surgery.
For my local application, i have extended these call objects: For instance, the doctor has an additional password field so the doctor's password can be stored locally. Now my local objects are also Serializable, and i also use this to send these around through the local network.
What is the easiest way for me now, to use objects of my extended implementations in a remote call to the server? The server obviously can't reconstruct my serialized implementations, because he doesn't know my specialized classes.
Do i have to manually create a un-extended bean object from my extended one by basically copying all the fields except the new ones? or is there a better/easier way to do this? Overwriting the serialization methods is not an option because, as i stated above, i still need my local objects to be normally Serializable too.
The server obviously can't reconstruct
my serialized implementations, because
he doesn't know my specialized
classes.
Unless your server can get to know about your specialized classes via a jar in the classpath, you won't be able to have it unserialize your classes.
Creating proxies could be an angle to explore, but with no guarantee this would work (not enough details about your specific situation).
An easier solution is to use a root class for your beans, containing or extending a hash map and store the properties/values in it. Instead of creating getter and setter for each property, implement only one pair and provide the property name as a string.
The server won't have any issue to unserialize it, unless one of the Serializable object in the map is unknown to the server. This method allows you to add any extra bean information in it and the server will always know how to deal with it.
There is also a trickier angle you could try. The class Class is serializable by itself. Therefore, if you transferred it before you transfer your beans, may be the server could learn about it first. I have never tried this myself, so I don't know if it would work. Just an idea.
I have a list of services which can be identified by names. Every service has a set of parameters (IP address, port, availability and so on). There are also method which can be applied to the services (close connection, open connection, send a message to the server, check if it is responding and so on).
So, I thought it is a natural approach to create a Server class and represent real servers as objects of this class.
But than I realized that it is not really convenient. For example I have a name of the server (just a string) and I would like to do something with this server. Then I need to have a map which maps name of the server to the object representing this server? It does not seems to be an elegant solution.
What I decided is to have a class containing a set of static methods. And then, for example to use it in the following way: ServerClass.sendMessage("NameOfServer","MyMessage") or for example ServerClass.close("NameOfServer") or ServerClass.getIP("NameOfServer").
Is it a good solution?
An advantage of having a class with various instances is that it provides a kind of type safety. If you have
Server myServer = ServerRepository.getServer("NameOfServer");
if (myServer != null) myServer.sendMessage("MyMessage");
then you know before you send the message if your server name has a typo in it (because your repository can't return a matching message).
Do all of your servers expose the same services, or are there some that are dependent on the server. As an example if you have both FooServers which have a method doFoo() and BarServers with a method doBar() but Foo has no doBar and Bar has no doFoo, then this is likely a bad idea as your ServerClass will potentially expose methods that are meaningless to potential callers. If however you know all of your servers are going to be FooServers than this may be a valid approach as you can centralize common code. I would say be careful that your code remains maintainable and you are not forcing common behavior where it needs to be customized, or you end up adding a multitude of extra arguments to indicate "special cases" where you need to the behavior to vary slightly for one reason or another.
My problem is that I'm working on a project that requires me to run multiple instances of someone elses code which has many static attributes/variables, which causes all the instances to share those resources and, well, crash. I can run multiple instances of this other person's program if I create a .jar file off of it and open it multiple times by running the .jar in windows, but running calling the "main" method multiple times in my code (which is what I need to do) won't work.
I thought about creating a .jar and using Runtime.getRuntime().exec( "myprog.jar" ); to call the program multiple times, but that won't work for me since I have to pass an instance of my object to this new program and I don't think this solution would allow for that.
PS: This is also posted in the Sun forums, so I`ll post the answer I get there here or the answer I get here there naturally giving proper credit once I this is solved =P.
Remember that a static element in Java is unique only in the context of a classloader (hierarchy); a class is uniquely identified in a JVM by the tuple {classloader, classname}.
You need to instantiate isolated classloaders and load the jar using that class loader. Each loaded class (and thus statis elements) are unique in their classloader and will not interfere with one another.
I'd say you have three alternatives:
Refactor the legacy application so that it doesn't use static attributes. If you can do this, this may be the best solution in the long term.
Continue with your approach of launching the legacy application in a separate JVM. There are a number of ways that you can pass (copies of) objects to another JVM. For example, you could serialize them and pass them via the child processes input stream. Or you could stringify them and pass them as arguments. In either case, you'll need to create your own 'main' class/method that deals with the object passing before calling the legacy app.
I think you should be able to use classloader magic to dynamically load a fresh copy of the legacy application each time you run it. If you create a new classloader each time, you should get a fresh copy of the legacy application classes with a separate set of statics. But, you have to make sure that the legacy app is not on your main classpath. The problem with this approach is that it is expensive, and you are likely to create memory leaks.
The description is a little confusing.
If you are running the code multiple times, you are running multiple independent processes, each running in its own JVM. There is no way that they are actually sharing the values of their static fields. Java doesn't let you directly share memory between multiple VMs.
Can you elaborate more (ideally with examples and code) what the attributes are defined as and what kind of failures you are getting? This may be completely unrelated to them being static.
In particular, what exactly do you mean by shared resources? What resources are your programs sharing?
The proper approach was already suggested - using custom ClassLoaders. Another thing comes to my mind, which might seem ugly, but will probably do, and is a bit more object-oriented approach.
The legacy code is used for its operations, and it incorrectly uses static instead of instance variables. You can fix that using inheritance and reflection:
create (or reuse) an utility class that copies instance variables to static ones
extend the classes in question and provide the same instance variables as the static ones
override all methods. In the overriding methods use the utility to copy the state of the current object to the static variables, and then delegate to (call) the super methods.
Then start using instance of your class, instead of the legacy ones. That way you will simulate the proper behaviour.
Have in mind this is NOT thread-safe.