I'm trying to use the Java ASM library, and after quite a bit of research, I haven't found the solutions to a problem I'm having. I'm trying to make an application that does the following:
Reads classes from an external Jar file
Remove completely certain methods from specified classes
Print to console or store the modified class' compiled bytecode or compiled class contents, like from new String(cw.toByteArray()), cw being an instance of ClassWriter (Similar to how you would see if you edited a class file with notepad)
I have been able to read bytecode and the compiled class contents, but not remove methods. I haven't been able to find any working code, only partial code with very little explanation of how to implement it.
You can implement a ClassVisitor that overrides the visitMethod method and return null from this method without invoking super.visitMethod when you discover a certain pattern.
This way, the method in question is skipped and not added to the created class file.
Related
I have an .so file that I successfully integrated into android studio and I can load the file by calling System.loadLibrary.
Is there a way I can see what methods and classes I can use now with this library loaded?
Depends on how the library maps Java methods to native function pointers: it can do one or both of the following:
Dynamic symbols that start with Java_ are mangled names for the class and method name.
If the code uses RegisterNatives system call you will have to put a breakpoint on env->RegisterNatives and look at the surrounding code/arguments.
I've been trying to find an answer to this for some time, but I think part of my problem is that I don't really know how to phrase my question. I understand the that JVM ultimately preforms all the system calls at run-time that the Java program needs to make, my confusion is about the underlying way that Java classes tell the JVM to do this.
Take for example, the File class in the standard Java library. As far as I know, this is considered the most fundamental API for opening/creating files in Java. But, File is just another class right? So in theory I should be able to write my own File class from scratch which doesn't utilize the pre-exisitng one, right? How would I do that? What is happening inside the File class that tells the VM to actually create the file? I looked at the source code for the File class, and it looks like it calls another class called VMFile, but I could find no explanation of what VMFile is. When I looked at the VMFile source code, it just had function declarations with no definitions.
Thank you for your help.
The Java Native Interface (JNI) is the glue between Java classes and the OS. Native methods have a 'native' attribute (look it up in the JLS).
I have a jni dll that has functions being called from java. The problem is that this dll has all the java classes in the default package (in the dll "Java_classname_methodname"). It is impossible to get the source of this dll and it would take EXTREMELY long to rewrite. So I basically need to call the functions in this dll from java in a different package than default. I've tried for hours on end to rename the functions in the dll with a hex editor and several tools to modify the checksum and addresses in the dll but it's just too much for me because I have almost no experience with this. I would very much prefer this route, but I just don't have the proper tools or the know-how. So what I'm left with is trying to hardcode the package name in java. I tried using jna as described in this stack overflow post to do something like this:
Map options = new HashMap();
options.
put(
Library.OPTION_FUNCTION_MAPPER,
new StdCallFunctionMapper() {
public String getFunctionName(NativeLibrary library, Method method) {
method.setName(method.getName().replace("com.test.", "");
return super.getFunctionName(library, method);
}
}
);
Native.loadLibrary(..., ..., options);
But there is no setName in Method. Ideally I'd like to get this done without any extra libraries but I'm obviously not opposed to using something like jna. And before anyone asks, yes this is permitted by the library's usage license. Please don't tell me it's not possible because know that it's possible, just difficult. Whichever way it must be done I am willing to put in the work (either modifying dll or using java code with some external library). And by the way, I also need this done on .so and .dylib files eventually (not as important as dll). Thank you for your time.
I have a JNI dll that has functions being called from java. The problem is that this DLL has all the java classes in the default package (in the dll "Java_classname_methodname").
So the corresponding Java class with the native methods wasn't in a package either.
It is impossible to get the source of this dll and it would take EXTREMELY long to rewrite. So I basically need to call the functions in this dll from java in a different package than default.
Correct.
I've tried for hours on end to rename the functions in the dll with a hex editor and several tools to modify the checksum and addresses in the dll but it's just too much for me because I have almost no experience with this.
You may be able to alias the function names somehow, but it's been about 20 years since I practiced in this area.
I would very much prefer this route, but I just don't have the proper tools or the know-how. So what I'm left with is trying to hardcode the package name in java.
No. There is no package name to hard-code. What you're left with is trying to call native methods in a class without a package from a class in a package, which since 1.4 is not possible.
What you need to to do is either:
It is possible to call the package-less Java native methods via reflection. So, you can write a wrapper class that does that, which lives in the package of your choice, and the rest of your code can call the wrapper.
Or
As follows:
Write another Java class in the package of your choice with the appropriate native methods.
Create an import library from the existing DLL.
Write another DLL and link it with this import library.
Load this new DLL from your Java code.
Have this DLL use the RegisterNatives method on initialization, to register the existing JNI entry points in the old DLL under the new native method names & signatures.
Use javah to get the required native method names and javap to get the required Java signatures. Don't try to guess them by hand.
Don't ask me how this maps to .so files.
I have a large pre-compiled project with lots of packages and class files. I have extracted one of the class files and decompiled it and edited some of the code inside. Now I would like to compile the changed code and re-insert it back into the original pre-compiled project, but unfortunately the code keeps many references to Objects in the pre-compiled project so I cannot compile without having it be already in the project which creates a rather large paradox. is there any for me to do what I am trying to accomplish?
Just compile it with a classpath which refers to the existing class files (or the jar file that contains those class files). There should be no problem.
However, note that if you change any constants in the file, those changes won't be reflected in any other code that refers to those constants.
It would generally be a much better idea to recompile from the complete source code. It would also be a better idea to use the original source code than just the result of decompilation - do you not have access to the original source code? (If you don't, are you sure that what you're doing is even legal in your country? I'm not a lawyer, but you should at least check...)
I would recompile the whole thing to avoid problems, but if you MUST, try this and let me know if they work for you:
Instead of loading the class on your original project, load it using classForName http://docs.oracle.com/javase/7/docs/api/java/lang/Class.html
Remember that you cannot change the signature of the methods as this would indicate a different object since it wouldn't follow the same contract (interface).
Also keep in mind the serialVersionId What is a serialVersionUID and why should I use it?
I am trying to instrument a class file, but I was just wondering where annotations are stored in the class file format. I tried putting them in the interface table however, when I did that it only recognized them as an interface not as an annotation.
They are stored in the RuntimeVisibleAnnotations and RuntimeInvisibleAnnotations attributes for classes and methods class members, and the RuntimeVisibleParameterAnnotations and RuntimeInvisibleParameterAnnotations attributes for method parameters. You can find more detailed information about the classfile format in the Java VM Specification.
When trying to understand Java bytecode, a good starting point is writing in plain Java the class you would like to create using bytecode. Compile it, then use tools to retrieve generated bytecode.
Here's some tools I can think of :
ASM's Textifier (this class has a main method to make it easy to run)
Intellij IDEA Show bytecode view
Bytecode outline plugin for Eclipse