Manually add a method call to a class file? - java

I need to manually add a method call to a class file without decompiling and recompiling the code because It depends on thousands of other classes and I don't wan't have to do more than is nessescary. I know java but not how class files are made.
Any help is appreciated.
EDIT:
I am not the owner of the source and I need this to work on any computer, which means I cannot redistribute the sources and have them compiled realtime while my patcher is working.

You have the source code, and you have all other classes compiled. So you can recompile just that source file, passing compiled classes as parameters to java compiler with -classpath option.

You should use ASM or Javaassist to manipulate the bytecode. ASM is a little bit more complex and requires you to understand more about the JVM, but it's faster. Javaassist doesn't require you to know much about the JVM's internals.
However, I don't see why you can't just recompile that single sourcefile? If you only need to add this method once, it's very inefficient to learn ASM or Javaassist.

How about subclassing? Then you don't need to touch the sources.

So if you have the source code and want to add some methods into only one class. Then you don't have to worry about other classes even they are dependent on your current modified class. Re-compiling a file doesn't affect other classes. Since the output will be produced at run-time.

If your class is not declared final and the method you are interested is not final, you can extend the class and override just that method.

Just change the source code, recompile ! Everything will work fine. Subclassing won't work .Because Already existing classes won't know about the new subclass until you change their code to use the new subclass instead of old superclass.

For manual editing of classfiles, I'd recommend Krakatau. (Disclosure, I wrote it). It lets you disassemble a classfile, edit it, and reassemble. There are other assemblers out there, but AFAIK, Krakatau is the only one that supports all the weird edge cases in the classfile format.
The main caveat is that Krakatau by default does not preserve certain optional debugging attributes (specifically LineNumberTable, LocalVariableTable, and LocalVariableTypeTable), since there is no simple way to represent them in a human editable format, and failing to edit them when the bytecode changes will result in a verification error. Most likely you don't actually need this though so it shouldn't matter.
The other caveat of course is that you have to understand bytecode. But if you don't, you won't be able to manually edit classfiles anyway.

I got it now! I Created fake source files with the same names/methods but didn't add anything else except for class and method names. That way I only needed to pack the ones that are directly linked to my Class file. But now compiling takes a few milliseconds whereas it used to take around 124s, Lol. Works great!

Related

Reverse Engineer Java *.class file to change data type of variable

I have a problem with an old application which runs on a Java Tomcat server and the source code for the application is not fully available, but the .class files are obviously all running on the tomcat server.
Can I somehow manipulate the bytecode of a .class file (used by JVM) so that I can change a variables datatype (because this is what has to be done)? Or even reverse engineer it to its old .java source code?
I have used decompilers and javap command up to now. Can I somehow copy the whole Tomcat application and:
decompile it
do my changes
recompile it?
Well, if you decompile it to make changes and recompile, then you're not going to need to change the byte code directly.
If you change the type, you'll have to change the type of any methods (like getters and setters) that use the variable. Then you'll need to change the calls of any methods in all classes that CALL those methods, and the types of their variables that hold these values, etc. The good news is that, if you manage to decompile it successfully, your IDE will tell you where all those places are, assuming the new type is incompatible with the old type.
I would evaluate this as "theoretically possible", but problematic. With the little information you've given us, there's no way to know the size of the job AFTER you successfully decompile the entire application.
I have a wild and crazy idea; I haven't done this, but as long as we're talking about things that are theoretically possible...
IF you manage to decompile all the code and get a system that you can recompile and run (and I strongly recommend you do that before you make any changes), if you are able to identify where the int is that you want to replace with a long, and then all the direct and indirect references to it, hopefully (because it's just this file size limit that you mention elsewhere) you end up with only a handful of classes.
The decompile should tell you their names. Create new classes with the exact same names, containing (of course) all their decompiled code. Change the methods that you need to change.
Now put those classes in a jar that is searched before the jar containing the application. You're limiting the number of classes for which you're providing new .class files to just those. This makes it easier to see exactly what has been changed, for future programmers, if it doesn't do anything else. It's possible because of the way Java handles its runtime; the step that's equivalent to 'linking' in a traditional compiled non-virtual-machine language happens when the class is loaded, instead of at compile time.
I did that. Not exactly that, but something very similar. Instead of decompiling and recompiling, which is very long, and tedious, I directly edited the byte-code of the class file.
pros
You do not need to compile anything at all, you just edit a file
no SDK, no IDE, etc is necessary, just a java-byte code editor
for small changes you can get away with single method modification
cons
very-very error-prone even if you know what you are doing
no way to track changes as you do with git
will probably require modifying all dependent classes
you should have some knowledge about how compiled code looks like, and behaves before even attempting such a thing.
you will most likely break a law or two since this will not be for "educational" purposes
you will be marked as "the hacker" and every odd job will be forwarded to you
PS: I had to edit licensing class of a product to allow more users. The company writing it ceased to exist, so buying was not an option. We switched to a new product anyway, it was just temporarily.

How to add Java annotation over methods during runtime [duplicate]

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. :)

What's the point of using .class objects?

In the past few weeks, I've run into several different peoples' code using .class objects. For example, ArrayList of classes : ArrayList<Class> but how to force those classes to extend some super class?.
I looked them up: http://docs.oracle.com/javase/tutorial/reflect/class/index.html
I'm just wondering why you'd want to use .class objects. I can see getDeclaredFields() and getDeclaredMethods() being potentially useful, but I can't really think of concrete examples as to why I'd actually want to use the .class objects in lieu of something else. Could anyone shed some light on this topic?
Thanks in advance.
I think you misunderstood the concept. Class class has nothing to do with compiled classes (.class).
Class is a class that represents a Java class internal structure, such as fields, methods, etc... This is a compile-time entity, which you can use in your code (even before compiling).
.class is a compiled Java class file, which is Java bytecode. This is not a "code" entity (you cannot use it as a class or object in your code -besides as any file-) and it is not available before compilation.
Reflection (Class is part of the reflection package) is useful when you want to do advanced stuff with the code, like manipulating it, accessing its members, getting information from it, etc...
A typical example where you want to use reflection is making a Java debugger. Since any code can be run on the debugger, you need reflection to get information about the object instances and their structure and show this to the user.
Reflection is one reason to use it. Another good example is dynamically constructing objects at runtime.
For example, the Spring framework uses configuration files that contain the names of Java classes. Somewhere in that code, Spring needs to build object instances of those classes. In this way, the objects are created without the compiler needing to know anything about the Java classes at compile time.
This can be useful when developing an interpreter of a scripting language running on JVM, which has an ability to call Java methods.
Also, might be useful in a system allowing for plugin extensions.
Another use case:
InputStream is = MyClass.class.getResourceAsStream("/some/resource/in/the/jar");
Plug-in are a big use for this.
Dynamically load .class files which are in say, your plugins folder and execute some specified function from said files. Then, you can have 0 or more plug-ins and any combination of them installed for your application at a time.

How do I catch the read and writes in a java program?

I am trying to create a tool that can capture all the read and writes made by a java program. Also, I would like to know what fields of what object is access/modified.
I currently looked at:-
1) java.lang.instrument
I could not do much with that. I could not understand how to write an agent that can get access to the a running program and create a watch on different objects/fields and anything related. I would appreciated if you have any idea or information on that.
2) jvmti
I looked at jvmti and tried to create a jvmti tool, but I figured out that to get the objects, I would need the JVMTI_EVENT_OBJECT_ALLOC be a potential capability. But, I figured that, it is not. Moreover, I read that this event is not called for new command. Hence, at the moment, even this does not seem applicable.
So, I would like to know if you guys know any way to do what I want to do, either using the above mentioned methods or any other technique/tool that you may be aware of?
NOTE: I do not have access to the source code of the application. All, I have are the class files.
Check these out:
http://download.oracle.com/javase/6/docs/technotes/guides/management/jconsole.html
http://java.sun.com/developer/technicalArticles/J2SE/jconsole.html
http://jamonapi.sourceforge.net/
http://www.manageengine.com/products/applications_manager/java-runtime-monitoring.html
It's very easy to do with the ASM lib. Create a new Class Loader that instruments all classes before loading them and use it for loading the target classes. Create a new MethodAdapter and override the visitFieldInsn method. Then look for the PUTFIELD, PUTSTATIC, GETFIELD and GETSTATIC opcodes. Although this might look scary (as my explation is most likely gibberish), it's in fact pretty easy. Just download the ASM manual and you'll know how to do it in no time.
Edit: I was forgetting to tell that in order to be able to intercept the reads and writes of done by the JDK code you have to instrument those classes, save them to files and run the JVM with a modified bootstrap classpath, through command line argument -Xbootclasspath (java.* and some other packages; I believe that at least sun.* and javax.* also need this).
This may also be doable with AspectJ... but I'm not sure.

What settings affect the layout of compiled java .class files? How can you tell if two compiled classes are equal?

I have an app that was compiled with the built-in Eclipse "Compile" task. Then I decided to move the build procedure into Ant's javac, and the result ended being smaller files.
Later I discovered that adjusting the debuglevel to "vars,lines,source" I could embed the same debug information that Eclipse did, and in a lot of cases files stayed exactly the same size but the internal layout was different. And as a consequence, I couldn't use md5sum signatures to determine if they were exactly the same version.
Besides debug information, what can be the reason that 2 supposedly equal files get a different internal layout or size?
And how can you compare compiled .class files?
THere is no required order for things such as the order of the constant pool entries (essentially all of the symbol info) as well as the attributes for each field/method/class. Different compilers are free to write out in whatever order they want.
You can compared compiled classes, but you would need to dig into the class file structure and parse it. There are libraries out there for doing that, like BCEL or ASM, but I am not 100% sure they will help you with what you want to do.
The ASM Eclipse plugin has a bytecode comparer in it. You select two classes, right click, and do Compare With / Each Other Bytecode.
An important thing to note is that Eclipse does not use javac. Eclipse has its own compiler, the JDT, and so differences in the resulting .class files do not surprise me. I'd expect them to not be verbatim, because they are different compilers.
Due to their differences, there exists code that compiles with javac but not JDT, and vice versa. Typically I have seen the differences in the two become apparent in cases of heavy use of generics
Most importantly, the stack slots for local variables can be arranged arbitrarily without changing the semantics of the code. So basically, you cannot compare compiled class files without parsing and normalizing them - quite a lot of effort.
Why do you want to do that anyway?
as Michale B said, it can be arbitrary.
I work on systems that are using file sizes as security. If the .class files change in size, the class won't be given certain permissions.
Normally that would be easy to get around, but we have fairly complete control over the environment, so it's actually pretty functional.
Anyway, any time the classes that are watched are recompiled, it seems, we have to recalculate the size.
Another thing--a special key number is generated when the file is compiled. I don't know much about this, but it often prevents classes from working together. I believe the procedure is, compile class A and save it (call it a1). compile class a again (a2). Compile class b against class a2. Try to run b against a1. I believe that in this case it will fail at runtime.
If you could learn more about that key number, it might give you the info you are after.
For the comparisson you can decompile your class files and play with the sources generated. See this.
Is Eclipse doing some instrumentation to assist with running in the debugger?
Ultimately the configurations being used are probably making the difference. Assuming they are using the same versions of Java, there are a host of options that are available for the compile configuration (JDK compliance, class file compatibility and a host of debugging information options).

Categories