Java classloader tracing [duplicate] - java

I have two ClassLoaders which loads the same class. So, obviously these can't cast to one another. But I need to access an object created in the other ClassLoader.
I have access to both ClassLoaders. How can I use that object in the other class? I don't need to cast the object to match to the current ClassLoader.
But the issue is that the returned object's type is Object. So, I have to cast down that object to access some methods. How can I do that? Normal cast like the following causes ClassCastException, which I already know.
Mojo mojo = (Mojo) descriptor.getMojo();
descriptor#getMojo() returns an object of type Mojo but the method returns Object. How can do this?
Let me know if you need further info.
I've read all the theories about classloading, but none has specified a proper solution for this.

AFAIK, no, you can't cast an object of a class loaded by one class-loader in another class loader.
One solution would be to create a "common" class-loader which loads the classes to be used by your custom classloaders. So in your case, you'd have a new classloader which would load the given class and your custom classloaders would extend this classloader.
Another solution would be to pass around the "serialized" state between the two classloaders. Serialize one instance to a byte array and reconstruct the object in the other classloader by de-serializing the object stream.

Reflection isn't that bad, and is appropriate here.
Is this a Maven plugin, BTW?
You'll want something like:
Mojo mojo = (Mojo)descriptor.getClass().getMethod("getMojo").invoke(descriptor);
I'm leaving out a lot - particularly exception handling - but this should lead you to the Javadoc you need. It's quite good, but read carefully.
If you also have two Mojo classes, the cast will break, and you'll have to do more reflection to do whatever you need to do with the evil-twin Mojo.

I think better option to just store byte array instead of object. While deserliazing, get byte array back and convert into object.
I had the same issue and byte array approach worked.
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutput out = null;
try {
out = new ObjectOutputStream(bos);
out.writeObject(cachedValue);
byte b[] = bos.toByteArray();
//Store in DB, file wherever here using b[]. I am not writing code to store it as it may vary in your requirement.
} catch (IOException e) {
e.printStackTrace();
}
Read from byte array:
ByteArrayInputStream bis = new ByteArrayInputStream(<<read byte[] where you stored earlier>>);
ObjectInput in = null;
try {
in = new ObjectInputStream(bis);
<Your Class >cachedRes = ( Your Class) in.readObject();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}

Why you have 2 CloassLoaders, which loads the same class? This could be a programatic issue. It sounds like you are caching ClassLoader somewhere and re-use them in a wrong way. If this is not the case try a MultiClassLoader.
Create a MultiClassLoader which includes multiple other classloader. These MultiClassLoader you can use to load all Classes you wish. But you have to create these MultiClassLoader at the very beginning and not when the classes are loaded.
public class MultiClassLoader extends ClassLoader
You would have a collection of classloaders and in the findClass(...) you iterate over all these registered loaders.
protected Class findClass(String aName) throws ClassNotFoundException {
for (Iterator iter = multiLoaders.iterator(); iter.hasNext();) {
ClassLoader tmpLoader = (ClassLoader)iter.next();
try {
return tmpLoader.loadClass(aName);
} catch (ClassNotFoundException e) {
}
}
throw new ClassNotFoundException(aName);
}

The easiest way is to use reflection. This allow you to dó anything you Can dó in "normal" code.

I solved this issue by loading the fully qualified class using Thread's parent context loader.
As an example, using AbstractMojo here.
Thread
.currentThread
.getContextClassLoader
.getParent
.loadClass("org.apache.maven.plugin.AbstractMojo")

Related

Creating an object from a saved one in its constructor

To be clear: I have an object which is continiously changing its values during the runtime and I want to save the created and modified object on a file.
I found how to that and I found also how to read back the object saving it into one another. But the question is: is it possible to call the class constructor of my object with the only parameter of the file in which the object I want to retrieve is stored?
NeuralNetwork(File fs){
ObjectInputStream ois;
changeFileSave(fs); //just sets the file as savefile for the future
try{
ois = new ObjectInputStream(new FileInputStream(_saveNet)); //_saveNet = fs
this = (NeuralNetwork) ois.readObject();
}
catch(Exception e){
//error message
}
}
It gives me an error on 'this ='
If it's possible how do I do something like this?
Thank you
The keyword this is a read-only reference, you can never write this = even in the constructor. Moreover, the constructor in java does not return anything.
You would have to take the object you've read and map its properties one by one (or using reflection) to the properties you have in the object you're instantiating.
However, I would submit that by passing a file to a constructor and doing the IO in it you are violating separation of concerns. By writing things this way, you have forever tied a neural network to a File, with a whole host of attendant issues, including (not limited to) the fact that you may be storing your values elsewhere at some point.
IMO you are better off using a factory pattern to build your object and making your NeuralNetwork object a plain object. Then the ambiguity disappears because your factory method can simply return (NeuralNetwork) ois.readObject();
this = (NeuralNetwork) ois.readObject();
Consider this as a hidden final argument that points to the instance that is executing the method. Its value cannot be changed. If you want to make a variable point to an instance, there's no problem with that, as long as you don't use this.
What you want to do is more appropriate for a factory or factory method than for a constructor. Use one of this patterns (or a static method if you want to keep it very simple) to create your instance from the file. Not sure if you need many instances of that class, but if you only need one, you should consider using a Singleton getInstance() method instead the previously mentioned.
You can't assign this, since it is readonly. this always points to the instance itself and is used throughout the life of the object to access its methods and attributes.
If you want to create an instance of your NeuralNetwork class by reading data from a file, you could use a factory method:
public class NeuralNetwork {
private NeuralNetwork() { // private constructor forces us to use the
} // factory method to create instances
public static NeuralNetwork loadFromFile(File fs) {
ObjectInputStream ois;
this.changeFileSave(fs); // just sets the file as savefile for the future
try {
ois = new ObjectInputStream(new FileInputStream(_saveNet));
return (NeuralNetwork) ois.readObject();
}
catch(IOException e){
throw UncheckedIOException(e);
}
}
// other methods and attributes
}
Then, wherever you use your NeuralNetwork class and need an instance, use:
NeuralNetwork network = NeuralNetwork.loadFromFile(someFs);
// use network instance and have fun with it here
Note 1: I've defined a private constructor to force everyone use the loadFromFile factory method to create an instance. This means that this class can only be created from within a static method of this class.
Note 2: I've also rethrown the exception with an unchecked exception. This is personal taste. I wouldn't just log the exception and go on. Instead, I would throw the exception so that the caller handles it properly, because it doesn't make any sense to go on if an instance of the class hasn't been created. If you don't want to rethrow the exception as an unchecked one, just don't catch the original IOException and add a throws IOException clause to your factory method. This would force the callers of loadFromFile to catch the IOException and handle it.

Intercept SOAP RPC method response without EJB

I'm working on a project revamp for a company, where they want to split their system between front-end/client and back-end/server (more like a middleman between the front-end and the database server), and I'm supposed to use JAX-WS RPC and maintain the current functionality.
By maintaining functionality they mean that some methods are supposed to return null, which is forbidden by WS-I.
Searching for possible solutions, I stumbled upon this article: http://victor-ichim.blogspot.com.br/2011/03/rpcliteral-and-null-object-pattern.html which basically solves a similar problem by using EJB Interceptors to intercept and replace null results with empty objects.
Working around the concept, I thought of intercepting the results just like so, replacing null with something like a string template, intercepting it again on the client and replacing that template back with null.
My questions are:They don't use EJB by default, so no Interceptors per se. Is there some implementation that could work for both Tomcat and JBoss?
Even if I'm able to intercept the return server-side, how could I do it client-side?
If I can use SOAPHandlers, how can I avoid raising the SOAP Fault for trying to return null?
Since I also had problems with JAXB not handling interfaces, what I ended up doing was using the #XmlJavaTypeAdapter annotation to enable (selectively, since every return and parameter that could practically be null needs to be annotated) converting values from and back to null, in sort of a hackjob manner. I created a generic-ish adapter for Serializable objects, and followed the same sort of approach for other kinds of Objects:
public class SerializableAdapter extends XmlAdapter<String, Serializable>>{
private static final String NULL = "'NULL'"; // Will hopefully never collide
#Override
public Serializable unmarshal(String e) throws Exception {
if (e == NULL) {
return null;
}
byte [] eB = e.getBytes("ISO-8859-1");
InputStream iS = new ByteArrayInputStream(Base64.getDecoder().decode(eB));
ObjectInputStream oIS = new ObjectInputStream(iS);
return (Serializable) oIS.readObject();
}
#Override
public String marshal(Serializable o) throws Exception {
if (o == null) {
return NULL;
}
ByteArrayOutputStream bAOS = new ByteArrayOutputStream();
ObjectOutputStream oOS = new ObjectOutputStream(bAOS);
oOS.writeObject(o);
return Base64.getEncoder().encodeToString(bAOS.toByteArray());
}
}
And then annotated every Serializable instance with #XmlJavaTypeAdapter(SerializableAdapter.class) since using package-level #XmlJavaTypeAdaptersdidn't work for some reason, and so forth for other cases. JAXB seems to eagerly cast the types encoded to and from when calling the adapters, so it will compile just fine even if the object to be marshalled isn't an instance of the expected class/interface, and throw exceptions only at runtime.
I don't recommend doing it this way, since it will require annotating every single method/parameter or package, and will break at the first one that didn't get annotated and yet received null. This very adapter still serves a purpose for cases where I need to work with interfaces, and the implementing classes also implement Serializable, although there are cases that still need specific adapters, but that's usually badly thought-out code.
Partially because of the hackness of this and the hassle of annotating everything, I managed to convince the company to move away from SOAP RPC bindings, so I was able to have null parameters and returns without this.

Create implementation of Java class dynamically based on provided dependencies at runtime

I'm trying to determine the best way to create a new instance of a class based on which classes are available on the classpath at runtime.
For example, I have a library that requires a JSON response to be parsed in multiple classes. The library has the following interface:
JsonParser.java:
public interface JsonParser {
<T> T fromJson(String json, Class<T> type);
<T> String toJson(T object);
}
This class has multiple implementations, i.e. GsonJsonParser, JacksonJsonParser, Jackson2JsonParser, and currently, the user of the library is required to "pick" their implementation to be used based on which library they've included in their project. For example:
JsonParser parser = new GsonJsonParser();
SomeService service = new SomeService(parser);
What I'd like to do, is dynamically pick up which library is on the classpath, and create the proper instance, so that the user of the library doesn't have to think about it (or even have to know the internal implementation of another class parses JSON).
I'm considering something similar to the following:
try {
Class.forName("com.google.gson.Gson");
return new GsonJsonParser();
} catch (ClassNotFoundException e) {
// Gson isn't on classpath, try next implementation
}
try {
Class.forName("com.fasterxml.jackson.databind.ObjectMapper");
return new Jackson2JsonParser();
} catch (ClassNotFoundException e) {
// Jackson 2 was not found, try next implementation
}
// repeated for all implementations
throw new IllegalStateException("You must include either Gson or Jackson on your classpath to utilize this library");
Would this be an appropriate solution? It seems kind of like a hack, as well as uses exceptions to control the flow.
Is there a better way to do this?
Essentially you want to create your own JsonParserFactory. We can see how it's implemented in the Spring Boot framework:
public static JsonParser getJsonParser() {
if (ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", null)) {
return new JacksonJsonParser();
}
if (ClassUtils.isPresent("com.google.gson.Gson", null)) {
return new GsonJsonParser();
}
if (ClassUtils.isPresent("org.yaml.snakeyaml.Yaml", null)) {
return new YamlJsonParser();
}
return new BasicJsonParser();
}
So your approach is nearly the same as this, except for the use of the ClassUtils.isPresent method.
This sounds like a perfect case for the Service Provider Interface (SPI) pattern. Check out the java.util.ServiceLoader documentation for an example of how to implement it.
If only one of the implementations (GsonJsonParser, JacksonJsonParser, Jackson2JsonParser) would be present at runtime and there is no other option, then you'd have to use Class.forName().
Although you can handle it a smarter.
For example, you can put all the classes into a Set<String> and then loop over them. If any one of them throws exception, you can just continue, and the one which does not, you can do your operations.
Yes, it is a hack, and your code would become library dependent. If there could be any chance that you can include all three implementations of your JsonParsers in your classpath and use a logic to define which implementation you have to use; that would be a much better approach.
If this is not possible, you can continue with above.
Also, instead of using plain Class.forName(String name), you can use a better option Class.forName(String name, boolean initialize, ClassLoader loader) which will NOT run any static initializers (if present in your class).
Where initialize = false and loader = [class].getClass().getClassLoader()
The simple approach is the one SLF4J uses: create a separate wrapper library per underlying JSON library (GSON, Jackson, etc.) with a com.mypackage.JsonParserImpl class that delegates to the underlying library. Put the appropriate wrapper in the classpath alongside the underlying library. Then you can get the current implementation like:
public JsonParser getJsonParser() {
// needs try block
// also, you probably want to cache
return Class.forName("com.mypackage.JsonParserImpl").newInstance()
}
This approach uses the class loader to locate the JSON parser. It is the simplest and requires no 3rd party dependencies or frameworks. I see no drawbacks to it relative to Spring, Service Provider, or any other method of locating resources.
Alternately use the Service Provider API, as Daniel Pryden suggests. To do this, you still create a separate wrapper library per underlying JSON library. Each library includes a text file at location "META-INF/services/com.mypackage.JsonParser" whose contents is the fully qualified name of the implementation of JsonParser in that library. Then your getJsonParser method would look like:
public JsonParser getJsonParser() {
return ServiceLoader.load(JsonParser.class).iterator().next();
}
IMO this approach is unnecessarily more complex than the first.

Is runtime-compiled-class instantiation & usage possible in Java without reflection?

I would like to know if there exists any kind of library or workaround to use my runtime compiled classes ( I dynamically generate my classes, writing .java, then compiling them in .class all of this happens at runtime) without using a reflection library?
Loading using reflection I always have to work like this:
//path where my newly generated classes are
File file = new File("e:\\tmp");
// Convert File to a URL
URL url = file.toURI().toURL();
URL[] urls = new URL[]{url};
ClassLoader cl = new URLClassLoader(urls);
Class cls = cl.loadClass("eu.dataaccess.footballpool.TGoal");
// Create an instance of the class just loaded
Object o = cls.newInstance();
Method method2 = cls.getDeclaredMethod("getIMinute");
Object result2 = method2.invoke(o);
My question is if it's somehow possible to use at runtime
TGoal x = new TGoal();
and
x.getIMinute();
EDIT: It seems it is impossible to act the way I hoped to. I modify my question so: is it possible to load a whole package at runtime, in a way that the classes of the loaded package are able to communicate each other without the method.invoke, meanwhile the main activation of the package is done with the method invoke() ?
I tried without any luck, i have some "error: cannot find symbol", it seems the runtime-loaded classes can't communicate each other
If you're not using the reflection api you have to instantiate classes via the new operator. This requires having the class file at compile time. So it is not possible. If your class TGoal is implementing an Interface IGoal, then you can cast your Object o to IGoal. This enables you to work with your Object like with any other object without using the reflection api.
You can do
x.getIMinute();
by using interfaces, but AFAIK you cannot create new class instances without reflection.
Instead, to call methods of your dynamically created objects, you
can declare an interface:
public interface MinuteGetter{
public int getIMinute();
}
Your dynamic objects have to implement his, than you can do:
Class cls = cl.loadClass("eu.dataaccess.footballpool.TGoal");
// Create an instance of the class just loaded
MinuteGetter o = (MinuteGetter) cls.newInstance();
o.getIMinute();
If applying an interface to your code is not an option for you, you can try to give a try to AnonymousClassLoader. See this detailed post about it.
It work only on Java 7, and please note that I never used it, so how don't know if it offer better performance than reflection.
Are you sure you have to create the Code at runtime? The easiest way is to avoid this.
If the TGoal x = new TGoal() doesn't have to happen in this program, then create a main function in the generated code and start a second java application.

How do I replace an existing Singleton object with one from a saved file using ObjectInputStream?

I'm making a Java application that has basic Saving / Opening capabilities. All I need to save is the instance of my class ModeleImage which is a Singleton. My saving apparently works and looks like this:
ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream(file));
outputStream.writeObject(ModeleImage.getInstance());
outputStream.flush();
outputStream.close();
Now I'm trying to open that file with ObjectInputStream. I'm not sure if there's a way to simply replace my Singleton (ModeleImage) with the saved one but right now I'm only trying to copy and replace each attribute. My opening looks like this:
FileInputStream fis = new FileInputStream(fileChooser.getSelectedFile());
ObjectInputStream ois = new ObjectInputStream(fis);
//Get each attribute from the file and set them in my existing ModeleImage Singleton
ModeleImage.getInstance().setImage(((ModeleImage) ois.readObject()).getImage());
ModeleImage.getInstance().setLargeurImage(((ModeleImage) ois.readObject()).getLargeurImage());
ModeleImage.getInstance().setHauteurImage(((ModeleImage) ois.readObject()).getHauteurImage());
ModeleImage.getInstance().setxImage(((ModeleImage) ois.readObject()).getxImage());
ModeleImage.getInstance().setyImage(((ModeleImage) ois.readObject()).getyImage());
I also put try/catch around each. The problem is that my opening part catches an IOException when trying to replace attributes.
ModeleImage.getInstance().setImage(((ModeleImage) ois.readObject()).getImage());
//This catches an IOException
What am I doing wrong?
Is it because it's a Singleton or am I misunderstanding how ObjectInputStream and readObject() work?
By using a built-in feature of the serialization mechanism, you can enhance the normal process by providing two methods inside class file. Those methods are:
private void writeObject(ObjectOutputStream out) throws IOException;
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException;
Implement this methods by ModeleImage class and you will control all aspects of serialization and have access to internal state of singleton.
You should only be calling readObject() once since you only wrote one object:
ModeleImage image = ois.readObject();
ModeleImage.getInstance().setImage((image.getImage());
ModeleImage.getInstance().setLargeurImage(image.getLargeurImage());
ModeleImage.getInstance().setHauteurImage((image.getHauteurImage());
ModeleImage.getInstance().setxImage(image.getxImage());
ModeleImage.getInstance().setyImage(image.getyImage());
What you should do is have a static block that checks an instance of your class that you serialized. If it can, find it, it sets it to your singleton instance (thus making sure you load the one from the file). If it can't find it (perhaps first time your program is launching), then it should create an instance and assign it to your singleton variable.
You could create a save method or what not, or override the finalize method to save off your singleton so that way you can check for it in the static block on next time it is class loaded.
Make sense?
Implement readResolve on your serializable Singleton class to ensure there is only ever a single instance and override the properties there, i.e.
private Object readResolve() throws ObjectStreamException
{
instance.setImage(getImage());
instance.setLargeurImage(getLargeurImage());
...
return instance;
}
this concept is described nicely on http://www.javalobby.org/java/forums/t17491.html or check out http://docs.oracle.com/javase/1.3/docs/guide/serialization/spec/input.doc6.html for more on readResolve(). Hope that helps.

Categories