is there any way to do the following. so i have a project.jar file, inside it i need to modify the string passed to some method of let's say classA.class. for example, let's say this classA.class has a method named
change(String a, String b)
what i all want is to do the following as the first line of the code inside this method as follows:
a = a + "hi";
i want to modify the .class file directly, without needing to recompile everything again. then after that i would update the jar file with the new class file. is it possible? if yes can anyone show an example? thanks a lot in advance!
Yes it's possible with byte code editors. Commonly you can use aspectj together with compile time weaving to modify a class file. You can also use libraries such as BCEL, cglib etc.
However, for the use case you are describing you typically don't need to edit a class file. You can just wrap your object in a proxy or modify it's behaviour using AoP style of programming (as supported by e.g., aspectj)
There are tools to manipulate byte code dynamically, such as ASM: http://asm.ow2.org/
another way could be instrumentation. when you are loading the class you could manipulate the bytecode before using it. there are some good libraries for this, for example javassist from jboss. i think aspectJ works similar.
but why you want to change the bytecode, compile it and add it to a jar file again? are you needing the source code? perhaps you could use some de-compiler to get the source code, if you need it. a good tool is http://java.decompiler.free.fr/.
Related
So here's my situation:
I am running a Java Client/Server architecture that has high CPU usage and I'm trying to reduce the lag time on the main "server" thread. I have been profiling the server with YourKit to identify the CPU-hogging code.
The problem is:
I am using someone else's code, and because of the way it is written, it is impossible to decompile, then recompile without using a special obfuscator which I do not have access to (no I am not violating any copyrights or anything).
What I am currently doing:
To modify the class files without worrying about obfuscation, I have been using Storyyeller's amazing Krakatau decompiler (https://github.com/Storyyeller/Krakatau) to disassemble class files into assembly files.
I manually edit the .j assembly files while looking at a Jasmin reference page (which takes FOREVER and I often mess up), then reassemble them into class files and run them again.
What I want to do:
Instead of painstakingly editing the assembly, I was wondering, does anyone know of a way to convert .java Source Code to .j Assembly code?
Also, if I simply decompile the .class files, is it possible for me to simply recompile them even though the packages for the imports do not exist?
import com.bazinga.*;
public class MainThread{}//compile this even though package com.bazinga doesn't exist?
If anyone knows ANY WAY I could do this, I would really appreciate it!
Instead of painstakingly editing the assembly, I was wondering, does anyone know of a way to convert .java Source Code to .j Assembly code?
Yes and no. The obvious answer is that you can just compile your code and then disassemble the resulting classes. However, this is not always helpful, because compilation can be context dependent (such as inlining static final constants, or handling of nested classes). Additionally, if you plan to add your code into an existing method, you have to be careful to not use existing local variable slots or clobber the operand stack.
My best advice is to try to isolate your modifications as much as possible. For example, if you want to add code to the jar, instead of inserting it into an existing class, just write the code you want to add in Java, compile it and add the classfiles in. Then modify the target class to call into your own class.
As for imports, you can compile against stubs. Just create a dummy class with the name you want, and optionally dummy methods for anything you need to call. The implementations can just be {throw null;} or similar, since you won't actually be executing them ever, they just need to exist to satisfy the compiler during compilation.
i would like to know if it is possible to somehow read data from a text file and use it to tell java what libaries to import. I dont think its possible in java but what about groovy?
With groovy 1.8, it is possible to dynamically add imports to a script executed with GroovyShell. In particular, take a look at org.codehaus.groovy.control.customizers.ImportCustomizer. There's a good example of how to use this here: http://mrhaki.blogspot.com/2011/06/groovy-goodness-add-imports.html.
You can't totally avoid having 'import' statements, but it is an important part of many implementations of dependency injection that the actual dependencies are defined in a config file (ie. external text) and this information is loaded at runtime.
Groovy has a "import handler", class (interface to be true) GroovyResourceLoader, a kind of event is fired for every import required by "main" source. Is works in cooperation with GroovyClassLoader and maybe not with GroovyShell. I understand that my answer is in different area that "automatically add some hidden imports" - I speak about "classic imports".
Is there a way to modify .class files in order to add Java annotations to certain methods? Basically I want to traverse methods of each class file in a jar file and annotate certain ones. Note that this is not at run-time while using the jar file. Rather, after I'm done I want to have modified class files with the annotations.
I do have access to the source code, so if there's an automatic source code modifier, that would work as well...
I'm assuming I'll need a tool such as Javassist or ASM. If so, which one should I use and how would I go about it?
Actually, this is a classic use case for AspectJ:
declare #method : public * BankAccount+.*(..) : #Secured(role="supervisor")
While I will grant you that direct byte code manipulation is more powerful, AspectJ is much more user-friendly, and it immediately gives you compiler warnings when you are doing something wrong.
Also, if you use Load Time Weaving, you can leave the original library jar unchanged, because the weaving happens at class-load time.
Reference:
Declare Annotation
AspectJ in Action (book)
Googling for an hour or so turned this article up which seems to completely answer my question: use ASM. To write class files using the changed bytecode, use ClassWriter.
Well, time to get to work then, I guess. :)
I want to create a one .java from the Java program. When I run the program, automatically one Java file will created in my project, and also create some run time (dynamic) variable in that file. How can I do this?
I know for this I have to use a Reflection API like Class and Method, but what are the methods in Class and Method to do this?
You cannot create new classes or methods using the reflection APIs. They are not designed for this. (The Class and Method APIs are for performing operations on object instances in a dynamic fashion.)
If you want to create new code on the fly, there are two basic approaches to doing this:
Generate Java source code, write it to a file, use the Java compiler to compile it to a bytecode file, and then load the bytecodes. (There are standard APIs for running the Java compiler within the JVM of a running application.)
Use BCEL or equivalent to construct a bytecode file from scratch, and then load the bytecodes.
Both approaches are tricky and computationally expensive. The BCEL approach is particularly tricky because you need to understand a lot about the JVM to do the job.
Apparently you want to create a new class at Runtime and use it. You can sure create a .javafile, compile it and load it from a custom class loader but that's probably not the best/easiest thing to do. Here are a bunch of solutions:
First of all if you want to extend an interface, you can use the Proxy from the Java Reflection API.
It you want to extend a class rather than implements an interface or create a class out of the blue you need to use a library to create bytecode. You can find a bunch of them on http://www.java-opensource.com/open-source/bytecode-libraries.html. Among these libraries I like javassist mainly because it is the only library to my knowledge letting you enter Java code directly rather than bytecode.
A last solution should be to use a framework like Groovy or BSH to interpret pseudo-java code.
No, you can't generate new .java files using Reflection. You could perhaps create a new class, and use this class, in runtime, but you can't write that class out to file in the form of a .java source file.
Have a look at the JustAdd framework for instance. This framework solves this type of problems IIRC.
Java is a strongly typed language( As opposed to a weakly typed language). Simply put you need to have a Class (prototype) to create a instance of object. What you are trying to do is not natural in java (or any strongly typed language).
If you have to have this functionality in java, you need to use groovy. Groovy is a dynamic language that can run in Java JVM. You need to check Expandos in groovy.(ofcourse it still will not create a .java file).
I'm looking for some ideas on how to compile Java code with some other pieces of code missing (method calls). I am fully aware that javac will not allow you to compile Java files if cannot find all dependencies. But maybe there is some way how to bypass it, something like force compile.
My bytecode knowledge is not so good but I think some method invoke is just full package definition of class and method name with parameters. So if compiler just puts this data to class file and assume in running process dependency will be available (if not simple NoSuchMethodExp).
Only workaround so far I found is to create empty missing class files with empty methods to "cheat" compiler. Works perfectly but there should be easier way :)
Any ideas?
Use Interfaces.
Create the interfaces that have the methods you need. At runtime, inject (Spring, Guice, etc.) or generate (cglib ...) classes that implement the interface.
If you're modifying a jar, you can extract the class files you are not modifying to another directory and include that in the classpath. That way they will be available to the compiler.
Bad luck! Probably all you can do is to create mock objects for missing parts of code just to compile your code (empty methods, so the compiler can find it).
Another question - if you miss some classes, how will you execute that code?
UPDATED according to information provided:
Well, there is another option to modify classes in jar, you can use AOP, and to make it done read about AspectJ - actually for me this is the easiest option (typically you need to spend time mocking objects, writing empty methods, so I would contribute that time to study new technology, which will help you many times ;)
And btw the easiest way to implement it, if you use Eclipse, is:
install AJDT
create aspect project
create aspect which modifies code (depending on what you need to change)
add jar file you want to modify
immediately get modified code in
another already packed jar file
Sounds magically :)
In this case you don't need any dependencies in classpath, except for libraries which are needed for new code you add!
Methods aren't dependencies. They are part of the class definition. The only places the java runtime looks for method definitions is in the class def that was compiled at compile time and in its parent classes. If you're problem is that a super class is incomplete, I don't think I can help you.
If not, you could define some of these methods as abstract and than have a child class implement them.
What kind of code is missing? Normally this happens if you refer to libraries your compiler can't find. Maybe you simply need to extend the classpath the compiler is searching for classes.
If you really refer to code that is not available yet you need to implement at least those methods you refer to. But that sounds strange... maybe you can clear things up.