I have a piece of software, contained in a single .jar that is doing its job but sometimes I need to quickly push a bug fix necessitating replacing the .jar file in a central location, unfortunately if there is a currently running execution of this jar file if I replace it then it crashes with "class not found" error. I thought that once a jar file is executed the JVM will cache it in memory and won't do any reads from the disk but apparently this is not the case, how can (if possible at all) this be remedied?
EDIT:
The application is not web-based. It's normal Java SE.
JAR files are not loaded into memory in bulk, as other shared object libraries are. Their classes are loaded into memory on a demand basis, so if you remove a JAR file and a class lookup needs to occur, the file handle the class loader will be invalid (because the open file it referenced is now gone) and you will get an error.
Operating systems manage the file handles, so replacing an open file with a new copy is not going to fool anyone. You need to close the file first, which often can only be done by garbage collecting the class loader. If you are using the system class loader, then that means shutting down the JVM.
People have written frameworks to create custom class loaders that can be disposed independently of the system class loader; however, this does complicate class loading. While it can accomplish what you are asking, it cannot do so without restructuring your existing program to accommodate the lookup of classes in the framework's class loaders (and accommodating the loss and gain of class loaders over time).
If you want to try such a framework, see Christian's post. If you want to learn a bit more about how one project uses class loaders to facilitate its needs, take a peek under the covers of Apache's Tomcat, which restricts web applications within their own class loaders.
Often you might find that the correct answer really is to stop the service prior to deployment, and start it after deployment.
The only two possibilities I can think of are using JRebel or OSGi.
Related
This question already has answers here:
Is the use of Java's default package a bad practice?
(3 answers)
Closed 6 years ago.
I'm pretty new to Java, and I know what packages do. You use them to sort multiple files of a Java application together. However, is it standard to put it in a package if your application only has a single class? What are the pros and cons of doing this?
EDIT: I'm packaging this single class into a .jar file after.
From oracle documentation, it is clear that
The primary motivation for jar development was so that Java applets
and their requisite components (.class files, images and sounds) can
be downloaded to a browser in a single HTTP transaction, rather than
opening a new connection for each piece. This greatly improves the
speed with which an applet can be loaded onto a web page and begin
functioning. The JAR format also supports compression, which reduces
the size of the file and improves download time still further.
Additionally, individual entries in a JAR file may be digitally signed
by the applet author to authenticate their origin.
From Package Documentation of Oracle,
For small programs and casual development, a package can be unnamed
(§7.4.2) or have a simple name, but if code is to be widely
distributed, unique package names should be chosen using qualified
names. This can prevent the conflicts that would otherwise occur if
two development groups happened to pick the same package name and
these packages were later to be used in a single program.
It really depends on how you're compiling and running the program, but ultimately it's your choice.
Let's have a look at some of the different ways you might build your program.
1. Compiling the file with javac
If you're compiling the file using javac then the package will not matter. It will generate the .class file the same directory as the source file.
2. Compiling to a JAR File
If you're compiling to a JAR File, then the .class file will be inside the directories specified in your package name. Although this would not affect how the program is ran.
In both of these cases, I'd say that the package identifier is unnecessary for a single-file program. However, there is an exception.
The exception...
If ever you plan to use the class in a larger program, then adding a relevant package name would be essential.
This is because it would...
Prevent name collisions when other classes in the default packages have the same name.
Help people know whether or not your class is the one they want.
Can you imagine if 20 different developers made a List class in the default package, and somehow they all ended up in a project? It would be chaos! How would I choose the right List?
So in the case of writing a class that others will use in their own projects, you should definitely use package names.
It is probably non-production application if it has a single class and doesn't have any dependencies or resource files. So it is completely up to you how you will start your app.
If you want to distribute your app - make it in compliance with the standards, put it in a jar, publish to maven...
Java classloaders identify your classes by concatenating the package and the class name. So, if you don't use packages, the probabilities of name collisions are higher. Even though your app consists of only one class, you're going to reference many others, explicitly or not.
Also consider that you'll only be able to build very trivial applications with only one class, so probably that condition won't last forever.
Besides that, a class without package is a border case, so you'll probably find many tools that don't work with it.(I had this problem with the Web Service builder tool for Eclipse).
In short, use a package. It won't cause you any trouble, and (at least potentially) will save you many.
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.
Web applications for Tomcat are wrapped into a .war file and thrown into Tomcat. The application can use classes inside the war file and contained jar files. This separates the runtime-classes of Tomcat from the application classes.
When using storm (see storm-project.net), there is no similar segregation. Rather the recommended way requires to create a "fat jar", denoting a jar containing all the necessary class files after unwrapping them from their own individual jars. For simple situations this works, but the resulting fat jar must have all the META-INF/* files from all merged jars correctly merged, which does not work semi-automatically.
I would not be shy to write my own class loader which simulates something like a war-file. Except I have no clue how to intercept the default class loader that loads all the classes I deploy.
My theory is that one of the classes of my applications is loaded first by the default class loader. Presumably in its static-section I would cast the magic class loader spell such that all dependent classes will then be loaded by my own class loader, which would now how to get the necessary classes from whatever I deem suitable.
Any hints towards the general problems described as well as the specific magic needed are appreciated.
Intercepting the classloader: The default classloader is the one which loaded the class that is currently executing. So if you use a separate classloader to bring in the WAR's entry point, every class reference from it or its (run-time/creation) descendents will default to going through that classloader. That classloader can then decide what it should refer back to a higher-level classloader and what it should reload using its own resolution rules -- the simple rule "only ask the parent for things I don't have available in this plug-in", also known as "parent last", is often sufficient.
I'm working on a closed source java app that analyzes JAR files.
Since java can be easily decompiled, and obfuscation really isn't a big deal,
I want to provide an online service that will execute the app on my server and
return it's result much like fernflower here: www.reversed-java.com/fernflower/.
Problem is, I fear that's a recipe for disaster having my app load any potentially
harmfull jars on the server, even though i'm never running the jars.
All i'm doing is load them using URLClassLoader and JarInputStream.
Can a jar I am loading override classes in my original app in order to execute malicious code,
or mess up my program?
What are the risks in dynamically loading jars?
What are the risks in dynamically loading jars?
There are no risks of dynamically loading per se. The risks are really the risks of running untrusted code. If you do that without taking the appropriate precautions, you risk having your machine totally compromised.
If you are going to do this kind of thing, at the very least you should run untrusted code in a sandbox that stops it from doing anything potentially harmful. For instance, you need to block reading and writing local files, running external processes, using reflection, accessing system properties, and so on. And you may want to stop it creating threads, creating sockets, and other things that consume system resources.
Finally, you need to consider the case where some untrusted JAR has a method that is an infinite loop. This is a problem that can't be dealt with using security sandboxes. Indeed, the only bomb-proof way to get rid of a looping thread is to exit the JVM and restart it.
Can a jar im loading override classes in my original app in order to execute malicious code, or mess up my program?
I don't think it can easily override your classes, but there are lots of other ways for untrusted code to "mess up" your world; see above. (And if the untrusted code can execute reflective code, then it possibly can override your classes by messing around with the classloader's private data structures.)
I am looking for a way to reload a class into Java at runtime. The motivation is to make debugging more efficient. The application is a typical client/server design that synchronously processes requests. A "handler" object is instantiated for each request. This is the only class I intend to dynamically replace. Since each request deals with a fresh instance, reloading this class won't have any side-effects. In short, I do not want to restart the entire application every time there is a change to this module.
In my design, the Java process becomes aware that a .class file has been updated in the classpath in between requests. When this happens, the "handler" class is unloaded and a new one is loaded.
I know I can use the classLoader interface to load in a new class. I seem to be having trouble finding the proper way of "unloading".
Classes will be unloaded and garbage collected like any other object, if there is no remaining reference to them. That means there must be no reachable instance of the class (as loaded by that particular classloader instance) and the classloader instance itself must be eligible for garbage collection as well.
So basically, all you have to do is to create a new classloader instance to load the new version of the class, and make sure that no references to instances of the old version remain.
I believe that you actually need to have a hierarchy of classloaders, and in order to reload you actually get rid of the low level classloader (by normall GC means), and hence all the classes it loaded. So far as I know this technique is used by Java EE app servers for reloading applications, and there's all manner of fun results when framework code loaded in one classloader wants to use classes loaded somewhere else.
As of 2015 also java's class reloading is a missing feature.
Use OSGi to create a class reloading application.
Use jrebel for testing. There are a few others which does the same thing.
Use application server and externalize the parts which you want to reload into a separate web application. Then keep deploying/undeploying. You will eventually get some perm gen space overflow kind of errors due to dangling old ClassLoader instances.
Use a script runner to execute parts of changeable code. JSR-223 Java Scripting API support for the scripting language "Java".
I had written a series about class reloading. But all of those methods are not good for production.
The blog and source codes in google sources
IMHO this class reloading is messy in java and its not worth trying it. But I would very much like this to be a specification in java.