How to modify or substitute private method in a java class - java

I have a class which behavior I would like to change. I need to replace private method with another realization. Common reflection techniques allow to modify private variable or to invoke private methods. But I find little information about replacing entire methods.
I presume that there are advanced techniques to do so. May be its impossible with standard java reflection but there are probably other tools to recompile byte code in runtime.

Modify & replace:
One option is to mask the class with a modified copy (modify code, recompile code, add modified classes to the classpath before patched classes), similar to the approach used here to inspect how a normally unavailable method works.
If you do not have sources to modify, you can "reverse" almost any .class file into more-or-less readable source code using decompilers. Notice that, depending on licensing, you may not have permission to do so and/or to redistribute your changes.
Patch via agent:
You can also patch the methods using the -javaagent:<jarpath>[=<options>] commant-line option. The "agent" is a jar that gets to modify loaded classes and alter their behaviour. More information here.
Mock:
If you have control over where the methods are called, you can replace the target instance with a stubbed version. Libraries such as Mockito make this very, very easy:
LinkedList mockedList = mock(LinkedList.class);
// stubbing appears before the actual execution
when(mockedList.get(0)).thenReturn("first");
Even though Mockito does not support mocking private methods natively (mostly because it is considered bad manners to look at other classes' privates), using PowerMock allows you to do so (thanks, #talex).

You can't replace method in runtime (at least without hack into JVM). But you can replace whole class. There are several way to do it. For example you can use thing called "aspect".
But from my experience I can say that if you need to do this you have wrong turn somewhere in beginning of you way.
Maybe you better make one step back and look at whole picture

Instead of going for advanced techniques, there is a simple trick to achieve this.
If you class is part of an open-source jar, get source code of this class file from grepcode.com. Change the method that you want to change and compile it. And update your jar file/classpath with this updated class file.

Related

Is there a way to get rid "unused" and "MemberVisibilityCanBePrivate" when creating a public library

So I been messing around and created a library with my favorite methods that I use several projects. But those annoying unused method and method can be private (because it's intended to be used publicly but also used in the library somewhere else) warnings keep appearing and I want to keep the library clean.
Is there a way to tell the compiler that a class or file is intended to be used as a library?
Currently am using #Suppress("unused", "MemberVisibilityCanBePrivate") but this just feels wrong.
Those "annoying" unused method and method can be private warnings, actually are saying that you are neven calling those methods, and that's right when it comes to be an library, but it is wrong if we consider that all single public methdo must have a unit test for it. If you had a single junit testing such methods the compiler/checker would not bother you with that ;)
Solution: create junit for those library methods and will get ride of those messages and at same time you will get a safer code!

Replacing a method in a compiled .class file

Interesting question here. So I have a .jar I received and it is obfuscated, meaning when I decompile the .class files it doesnt show up 100% perfect so I cannot recompile it. However the only method I need to change has been converted perfectly (but the class does not)). Is there a way to somehow change the .java code and inject replace the method within the class file without totally recompiling?
If this fails im going to bytecode.
Thanks!
EDIT: As a follow up question / or a hack around replacing the WHOLE method. I'm really just trying to change a variable that the method generates locally. If there are any better ways to do that.
Depending on what you really want to do, I do not recommand to decompile / modify / recompile the code (be it for legal, maintainance, understandability, testability reasons.)
Bytecode manipulation may not be the best solution either, but if you want to follow this way have a look at the ASM project, it's a widespread bytecode manipulation framework used by many known projects.
If I were you I would first give a try to aspects (AspectJ.) The power of aspects is that you don't touch existing code, but tell the VM what to do when / before / after / in place of calling a specific method. It allows you to point out the exact context and change, enhance the behavior of the code, by writing your own code in a decoupled fashion.
Hope it helps.
Sorry, this is not an answer, but it is too long for a comment...
I am reflecting this code, not using it as a library. So I dont really need to "use" this code (aka I'm just reflecting and calling functions at runtime).
I'd call the "reflecting and calling functions at runtime" as using the code.
There might be the reasons why to do that, but I'd prefer to simply call the function as a library function if possible (which should be possible if you can do the same using reflection).
...and manually overload it.
There is nothing simpler that extending the class and override a "wrong" method. As of my understanding even if you want to "inject" the method, you have to have the code somewhere. How you will test such code? It'd be a lot easier to just extend the class... Can you specify in bigger detail what you want to achieve with a reasoning why you cannot use what I wrote above?
If you want to change just one method you can actually extend the class and then #Override the method!
Don't know if this is the perfect way to do it,but it works!

java code template

I'm trying to make a code template that will generate tostring, constructor from field, and a default constructor.
I already looked at Useful Eclipse Java Code Templates and in http://help.eclipse.org/galileo/index.jsp?topic=/org.eclipse.jdt.doc.user/reference/ref-tostring-templates.htm but it was not what I was looking for.
I tried this plugin http://eclipse-jutils.sourceforge.net/ but I still need to manually select an option in the menu (and it doesn't have a "constructor from fields" option).
I need to generate these methods and constructors for more then 100 classes so this the best way i found coz eclipse dont give tool to do it for more then one class and for this one class that he give this tool i need to do it one by one the (generate tostring ,constructor from field and also default constructor)
i will love to some help or some advice on a way to create these methods for all my classes, automatically.
thanks in advance.
I don't know of a plugin that will do this for multiple classes.
I'd just do it manually, even though it'd take time.
You could also use reflection and a scripting language like Groovy/JRuby/etc. to create the constructors, and rely on something like Commons' ToStringBuilder to create a toString, or just use reflection again.
(One problem is if you don't want a property in the constructor or toString you need to have a mechanism to tell the generator as much.)
I have just used Practically Macros, within a few minutes of install from the market place, I could generate *constructors*, getters / setters, toString, hashcode and equals (basically chaining the standard eclipse commands) in a single command. Just what I was looking for and saved me loads of time. I can also see a lot more uses for it, well done to Earnst (the creator).

DLLs for a dynamic Java program?

I'm currently working on a Java project where I have a set of data which I wish to output in several custom formats. I have a class for each format, which takes the raw data and converts it accordingly. However, to begin with I am only implementing two or three of these formats, but wish to allow more formats to be added at a later date without having to do a massive rebuild of the application.
My idea was to create a DLL for each of the format classes, and have my application pass the data to be converted to each of these. This way, I can create a DLL later on and have my main application accessing it. (I would gladly listen to any alternative ways of doing this, as someone who has done this in C++/C# before this felt like the logical solution but it may not be applicable to Java)
My problem is that I have absolutely no idea how to do this - in C++/C# I could write this in a few lines of code but I'm not sure how it works with Java. At the risk of asking a terribly vague question, how can I do this?
Answers are greatly appreciated and cookies and tea will be offered. :)
Thanks in advance,
M
Edit: Sorry, just to add: I am also unsure how to create the DLL, which must be in Java for this project, to be read in the first place. Thanks. :)
Rather than using a DLL per se, it seems like what is wanted is a plugin architecture of some sort.
One reason why I wouldn't recommend using a DLL unless it is necessary is that linking Java code with native code will require using the Java Native Interface (JNI) which would probably require more effort than a pure Java solution.
One relatively simple way to do so is to use the reflection capabilities of Java.
From the information given, I would probably go along the lines of the following:
Define an interface for the output format.
Create a Java class implementing the interface.
Have the class available from the classpath.
Dynamically load the class using reflection. (Using the Class.newInstance method can instantiate objects from class files loaded by the ClassLoader.)
With these steps, it would be possible to implement a simplistic plugin which wouldn't require a full rebuild when support for a new format is required.
Step 1: Define the interface
Let's say we end up with an interface like the following:
public interface Outputter {
public void write(Data d);
}
Step 2: Make an implementation class
Then, we'll make an implementation class.
public class TextOutputter {
public void write(Data d) {
// ... output data to text
}
}
Then, compiling the above, we'll end up with a class file called TextOutputter.class.
Step 3: Make the class available from the classpath
When running the main application, we'll need to have the above TextOutputter.class in the classpath. Normally, one would tell the JVM a list of places to consider as the classpath, and that should include the above class file.
Once that is done, we should be able to load the above class using reflection.
Step 4: Dynamically load the class using reflection
Now, when we actually want to load the above class, we'd do something like the following:
// Note: We load the class by specifying the fully-qualified class name!
Class<?> clazz = Class.forName("TextOutputter");
// Then, we instantiate the class.
// Note that the following method will call the no-argument constructor.
Outputter outputter = clazz.newInstance();
// Now, we can give data to the TextOutputter object that we loaded dynamically.
outputter.write(...);
The Class.forName method is used to attempt to find the TextOutputter class from the default ClassLoader. Once we obtain the class as a Class representation, we can then instantiate an object of that class.
Instantiating the object can be performed by using the Class.newInstance method. If something other than the no-argument constructor should be used, the Constructor of the class would have to be obtained proceed to instantiate the object from there.
The object instantiates via reflection is then placed into a Outputter variable, so the write method can be called on the TextOutputter.
Adding more formats would entail the above process, but changing the fully-qualified class name (e.g. for String, the FQCN is java.lang.String) is all that is needed to load up a different class.
In a nutshell, that's what it will take to dynamically load class files and use it from your application.
(Just as a side note, I did not actually compile the above code, so there may be some errors here and there, but I hope I could illustrate the process it will take.)
I've made such things.
i created an open java based plugin architecture POJO based,that even did reload on the fly of updated plugin classes.
JNI is the interface for dealing with native code.
The only technical part was to rewrite a classloader that enabled DLL reloading dynamically at runtime.
But if you do only make "offline" updates, no such things are needed.
You can load a new DLL at any time with System.loadLibrary(). However you may need to load a java class for it to bind to.
You might find using an OSGi container helpful as this supports both load and unloading of modules (including shared libraries)
I would suggest using karaf with iPOJO but there are many others.
If you want write native codes (compiled to a DLL) to be used in java, you want to look at Java Native Interface (JNI).
Update you can use System.loadLibrary(String libName) (if you know the library name and the library path is set) or System.load(String filename) (library filename) to load library (DLL) in java.
I think you can ignore the JNI path. I have the impression you're using the term dll for lack of a better word, you don't really need a dll.
You could do the same thing in Java, but you'd put your filters in jar files instead of dll.
Define an interface for the file format filters to implement
Put each implementation into a jar, in a specific folder (like 'filters')
At one point in the app, iterate over the folder, generate classloader for the jars
Use reflection to find all implementations of your interface, and create a class for each
Call the methods to do their job
That's basically it.
Java SE 6 introduces the ServiceLoader class:
http://download.oracle.com/javase/6/docs/api/java/util/ServiceLoader.html
If you want a proper modular approach consider the NetBeans Platform (especially if it is a desktop application) or OSGi.

Can eclipse convert/refactor a method to a class?

This seems like it should be fairly straight-forward, but I can't see anything obvious. What I basically want to do it to point at a method and refactor->extract class. This would take the method in question to a new class with that method as top level public API. The refactoring would also drag any required methods and variables along with it to the new class, deleting them from the old class if nothing else in the old class is using it.
This is a repetitive task I often encounter when refactoring legacy code. Anyway, I'm currently using Eclipse 3.0.2, but would still be interested in the answer if its available in a more recent version of eclipse. Thanks!
I don't think this kind of refactoring exists yet.
Bug 225716 has been log for that kind of feature (since early 2008).
Bug 312347 would also be a good implementation of such a refactoring.
"Create a new class and move the relevant fields and methods from the old class into the new class."
I mention a workaround in this SO answer.
In Eclipse 3.7.1 there is an option to move methods and fields out of a class. To do so:
Make sure the destination class exists (empty class is fine, just as long as it exists in the project).
In the source class, select the methods that you want to remove (the outline view works great for this), right click on the selection, and choose Move
Select the destination class in the drop down/Browse
Your members are now extracted. Fix any visibility issues (Source > Generate Getters and Setters is very useful for this) and you are all set.
This seems like it should be fairly
straight-forward...
Actually, Extract Class is one of the more difficult refactorings. Even in your simple example of moving a single method and its dependencies, there are possible complications:
If the moved method might be used in code you don't know about, you need to have a proxy method in the original class that will delegate to (call) the moved method. (If your application is self-contained or if you know all the clients of the moved method, then the refactoring code could update the calling code.)
If the moved method is part of an interface or if the moved method is inherited, then you will also need to have a "proxy method".
Your method may call a private method/field that some other method calls. You need to choose a class for the called member (maybe in the class that uses it the most). You will need to change access from "private" to something more general.
Depending on how much the original class and the extracted class need to know about each other, one or both may need to have fields initialized that point to the other.
Etc.
This is why I encourage everybody to vote for bug 312347 to get fixed.
Have you tried the Move feature of the Refactor group ? You can create a helper class and move there anything you want.

Categories