Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I replace a class file in compiled Java project?

Tags:

java

This may, and should be, a question that has been asked and answered many times over, but I just cant find the answer.

If I have a compiled application running on a server, can I compile the application on my local machine, and swap a class that I compiled on my local machine, with the one on the server?

In other words, can I replace a file that has been compiled and is on the server side, with a file almost identical that has been compiled, and is located, on my local machine?

Since the version on the server side has some hard-coded connections in other files, and I dont know all of the places, I would prefer to only swap the one file that I need, instead of doing a recompile for the application as a whole.

like image 349
Janis Peisenieks Avatar asked May 07 '12 09:05

Janis Peisenieks


People also ask

Can I modify .class file?

To modify a class file in an enterprise bean, you change the source code, recompile it, and redeploy the application.

How do you change a class in Java?

You can change the class path by using the JDK tools' -classpath option when you invoke the JVM or other JDK tools or by using the CLASSPATH environment variable.

How do you overwrite a class in a JAR file?

JAR files are just ZIP files. Use a tool like WinZip to extract all the files from the JAR, replace the . class file with yours, recreate the ZIP file using e.g. WinZip, rename it to . jar, overwrite the original JAR file.


3 Answers

The answer to your question is yes, you can replace a class file, but it is somewhat complicated in that you have to be sure that no other dependencies have changed.

For example, if the class you are compiling involved changing method signatures of methods that are used in other classes, you will need to replace those as well. As long as the method signatures of public, protected, or default methods aren't changed, you should be okay.

As a side-note, if this is something you do often, you'll quickly realize why objects are often passed into methods instead of individual parameters.

public MyObject getObject(MyObject2 mySecondObject)

vs

public MyObject getObject(int a, int b, int c)

When you need to add a new property to an object passed into a method, the method signatures don't change, but when you add or remove a parameter on the method signature itself, it creates a chain reaction on all dependencies, requiring that you compile and replace those class files as well.

As a final point to highlight, it's worth noting that changes you make to private methods or private variables, or even the definitions of a method, have no bearing or impact on other class files. The only thing that matters is that you uphold the contract that your methods have with other classes in that the inputs and outputs always take and return the same data types.

This highlights the importance of encapsulation of instance variables and how those dependencies are hidden from other classes.

like image 151
jmort253 Avatar answered Sep 30 '22 19:09

jmort253


Yes, you can do it. Moreover due to hot spot the class will be even reloaded at runtime, so you do not have to restart the server. This is very useful during development cycle.

But be careful replacing one separate class. If the class has references to other classes changed in your environment the replacement will fail on server.

like image 41
AlexR Avatar answered Sep 30 '22 19:09

AlexR


I assume you're talking about an 'offline' substitution (I mean you can restart the server).

In this case the following solution can be viable: Java uses classpath variable. There you define series of jars/folders where your process will look for files.

So you can do the following:

  1. Create your new class (it should be with the same name and reside in the same package) and compile.
  2. Create on server the folder where you're planning to store your updated class.

  3. Update the classpath variable (probably in the startup script of your application) so that this folder will appear before the rest of your classes.

  4. Restart your server. Now your new class will be resolved before the old one and loaded.

Caution: This works for 'standalone' applications and in general for those that don't fiddle with custom class loaders (for example this is the case in application servers).

More complex solution can be based on define your class loader that will take a look on such a folder (as I've described) and try to load resources from there.

Hope this helps.

like image 33
Mark Bramnik Avatar answered Sep 30 '22 18:09

Mark Bramnik