Is there a way to replace library classes? - java

Lets say that a lot of functionality are using methods from this class test.MyClass, but it's very slow and I'd like to code in JNI in hopes of improving the timing...
Is there a way to replace test.MyClass so that the library does not need to be changed, but the codes in the library will use the new test.MyClass with native implementations for certain methods from now on? It's the classic "PC is fine but the timing for Android is crap" problem.

Just create your test.MyClass in the same package/hierarchical structure as the one in the package you want to override. The classloader should load your implementation first and if it tries to load the one from other library the load will fail, because there can be only one loaded instance in the classpath.

Related

Dynamically loading jar from arbitrary url

Recently AWS Lambda added support for Java.
While this is great news, this come with a pretty severe limitation to the size of the code (50MB compressed). While this may be fine for other languages, Java uberjars can easily beat that.
So I've been toying with the idea of having a small loader that pull in, at runtime, a bigger jar from somewhere else. (set aside if this is a good idea or not for a moment).
From my initial research seems that a Custom Class Loader is the way to go. This is probably a no go for AWS Lambda.
Is there any other creative way this could be achieved?
I think ClassLoader, and more precisely URLClassLoader, is the way to go, and I don't know of any other solution to load code at runtime.
The class loader does not even have to be custom. It works with just a few lines of code, as demonstrated in this post.
If the jar files you will load fulfill a particular service for your application, also consider the handy ServiceLoader. It works on the same principle (in fact, you can pass it directly a ClassLoader), but makes it transparent to instantiate objects from the dynamically loaded library. Otherwise, you would have to get your hands a bit dirty, using something like:
Object main = loader.loadClass("Main", true).newInstance();

Using class loader to enable shared code between Java and Android

I am trying to build an application that runs under JavaSE and Android. Most of the code is the same between the two, but there are some specific functions that need to be separated. I use Eclipse. So I decided to put the shared code in a separate project, and then build one more project for Android and one for Java, which reference the shared project. I put all Java and Android specific functions in one class residing in the Java and Android specific projects. These classes are called UtilsJ (for Java) and UtilsA (for Android). The code in the shared project uses a factory to determine at runtime which version it needs to pick, and then calls the class loader to load the right class. Essentially: if property java.vm.name equals Dalvik, load UtilsA, else load UtilsJ (and of course cast to the Utils interface before returning).
My question is simply if this is a good idea or is something going to eventually break? I've never used class loader before. Any other suggestions how to implement this sharing would also be appreciated.
Generating an interface implementation dynamically is certainly a valid technique. For instance, having a data access interface that has multiple implementations; one each for flat files, MySQL and WebDAV. The program can pick an implementation at run time based on system/platform properties.
But this feels different. If I saw that I had a Java app and an Android app that had a lot of common code, my goal would be to create an Eclipse project that generates a jar file that I could just drop into the libraries of both projects. In that case, the jar file wouldn't contain any code that was incompatible with one platform or the other. So there wouldn't be any reason to have a platform-specific implementation.
Let's take your example some code reading an initialization file. If it's common code, you have an input parameter which is a file. On Android, maybe it's "/data/data/com.whatever.blahblahblah" and on Java you're getting the "user.dir" system parameter for the top level directories. But one way or another, it's a File, and you hand it to your common setup method. That's okay. But if your initialization file read code e.g. needs a Context to get a Resource to read the file for Android, then it's not common code. And it doesn't belong in a library jar for a JVM-hosted app.
So I think that in your case the platform-specific implementation classes are overkill. If it's common code, it's the same code — period.
Let's talk about another example in your comment. If you are using desktop Java, then you are probably using Swing or AWT, so you still have the same issue of running some network task off the UI thread, notifying when it completes, maybe even updating some progress indicator UI while it's processing. Same function, same operation, but the code is so different that I can't see how having it in the same library next to an AsyncTask version could be of any benefit.
And testing might get tricky. Obviously JUnit will work for everything, but some tests would need to run on a device or emulator.
I stated that it was a valid technique, and of course you may have other compelling reasons to choose the multi-platform option. You asked the question; is anything going to break? My answer is: Probably not, but why risk dealing with some heartburn down the road? Speaking for myself, I wouldn't do it. If I had to support multiple MVC apps, my common library would have nothing but M.

Creating a new Java application using the compiled class files

I have an application that is developed in Java that has nice GUI and all. I don't have the source code and also the dll's of that. But I have the compiled classes of that application (.jar files).
Now, I want to automate that application. I mean the application needs manual intervention.
Can I use that compiled classes so that I can use its functions to automate the functionality of that application?
If so, how would this be done?
You shouldn't have to "got the compiled classes out of that application (.jar)". A better idea would be to treat it just like any other 3rd party JAR and add it to your CLASSPATH when you compile and run.
You'll write your own class that instantiates an instance of that 3rd party class and calls its methods, just like any class you get from the JDK.
You may not be able to alter that class; you might not want to even if you could.
If you must have new functionality, the OO way would suggest that you should extend that class, if you can, and override its method according to your needs.
Put that .jar into your classpath and use what ever you want from that application. If you need to use private fields or methods also you can use Reflection API for that. There is no restrictions of using objects from .jar file.
You should beware of infringing on any copyrights if the application you are referring to is proprietary. Otherwise, any java decompiler will get you the source code from those class files.

dynamic creation of class at runtime from file

I'm looking for a possibility to load the Java code dynamically into a
class at the run time. The Java Code should be readed from an
XML-file. There are just some "If-Then" expressions and should be
added into one class and use it like any other class in my project.
Actually my file contains some rule codes which i want to load like cache and use
this class further
Does someone know if it is possible in java?
best regards
Abhij
I believe you can do this with CGLib, but I haven't done more than use it to mock classes at runtime. If dynamic code is a major aspect of your application you should consider using a language like Ruby which has much better support for running code read in at runtime.

Class Loading to an interface

I'm quite restricted in the platform I'm currently working on (JDK 1.3, BD-J). One JAR file I would like to use attempts to perform a self-integrity check on load and if it fails it goes into an inoperable state. It's quite difficult to find out why this is happening but most sources point to that it cannot find/access it self through the BD-J structure, so it dies.
This rules out using it at load time and instead to load it in the application itself. This is quite a large library so I have to create quite an amount of interfaces so I can cast a loaded object to it and potentially use it. This is where my problem lies.
The interfaces are loaded on normal load time and the library is then loaded during run time and casted to the previously loaded interfaces, is this a problem? I'm receiving ClassCastException
I've based the interfaces off the libraries public methods as best I can, but when I attempt to cast to an interface I receive the ClassCastException. Note: It all loads fine, I can access constructors and read the method names. Just when casting it for it to be useable it fails.
The interface packages are different in my project to that of the toolkit, does this matter?
I'm running out of ideas, is there something I have overlooked?
Thanks.
I'm not sure I fully grok what your problem is - maybe some more details about what the class hierarchy looks like would help in figuring out the situation. From what you wrote I can guess two possible scenarios:
.1. The classes you want to use do not implement any interface.
In this case no matter what you name your interfaces, it will not work, since the classes you're loading do not implement them. You're stuck with using reflection if you can't load that jar as part of the boot classpath.
.2. The classes you want implement some interface that you're trying to replicate.
In this case you interface implementation must match the exact qualified name of the interface the classes are implementing. Normally, when loading the classes from the jar, the class loader will pick up the interfaces from the system class loader first, thus loading your interfaces, and everything should work.
If they use some crazy internal class loader, though, they might still try to load their own interfaces. You could try to figure out if that's the case by using "-XX:+TraceClassLoading", although I don't know if the 1.3 jre will understand that option.
Now if you're willing to experiment more, you could also try another approach. Write your own class loader that loads both the classes from that jar and the code you want to run. That way, your code would be able to directly refer to the classes in that jar, but to start your application the "main" method will have to be one that initializes this classloader, loads the "real" main class using reflection, and executes its main() method also via reflection.
Most probably the classes are loaded by different class loaders. http://mindprod.com/jgloss/classloader.html may give some idea.

Categories