Saving the bytecode of a class modified with reflection - java

I have a java template class, of which I would like to modify a single String field.
I can instantiate an object of that class, get to its corresponding Class object, and modify the field using reflection, so far so good.
But how do I actually save the bytecode to the filesystem?
Since I think that if I get to the ClassLoader of the original template class, get to the InputStream and try to save to a file I will get the original (i.e. unmodified) class implementation. Is it so?
Ideally I would also need to change the class name to something more meaningful.
Can both things be done using pure java in the first place?
Or do I have to resort to external libraries?

When you modify a field using reflection, you're not changing anything about the class itself. It's just a fancy way of setting a variable. So there's no changed bytecode to worry about in the first place.
Anyway, AFAIK you can't easily get access to bytecode at runtime. The JVM creates classes from classfiles (either from files or in memory data) but once the class is loaded, there's no particular reason to keep the data around. Most likely, it will only keep an optimized representation that doesn't necessary correspond to the original classfile.
I think there are some APIs like Java agent that deal with bytecode at runtime, but it's not clear how well they work, partly because the JVM does optimize things.

Find an assembler/disassembler pair. Disassemble the class file, replace the string value, and compile back to class file. Note that the string constant can be referenced from several points, so probably you have to add a constant and change only one reference. If the new string value has the same length as the old one (in UTF-8 encoding), then you just replace constant with a binary file editor. If length are different, replacing would destroy the whole classfile structure.

Related

How to detect java local variables by an interface type and then find methods called on them?

I have some (maybe) strange requirements - I wanted to detect definitions of local (method) variables of a given interface name. When finding such a variable I would like to detect which methods (set/get*) will be called on this variable.
I tried Javassist without luck, and now I have a deeper look into ASM, but not sure if it is possible what I wanted.
The reason for this is that I like to generated a dependency graph with GraphViz of beans that depend on the same data structure.
If this thing is possible could somebody please give me a hint on how it could be done? Maybe there are other Frameworks that could do?
01.09.2015
To make things more clear:
The interface is self written - the target of the whole action is to create a dependency graph in the first step automatically - later on a graphical editor should be implemented that is based on the dependencies.
I wonder how FindBugs/PMD work, because they also use the byte code and detect for example null pointer calls (variable not initialized and method will be called on it). So I thought that I could implement my idea in the same way. The whole code is Spring based - maybe this opens another solution to the point? Last but not least I could work on a source-jar?
While thinging about the problem - would it be possible via ASM/javassist to detect all available methods from the interface and find calls to them in the other classes?
I’m afraid, what you want to do is not possible. In compiled Java code, there are no local variables in the form you have in the source code. Methods use stack frames which have memory reserved for local variables, which is addressed by a numerical index. The type is implied by what instructions write to it and may change throughout the method’s code as the memory may get reused for different variables having a disjunct scope. The names on the other hand are completely irrelevant.
When bytecode gets verified, the effect of all instructions to the stack frame will get modeled to infer the type of each stack frame slot at each point of the execution so that the validity of all operations can be checked. Starting with class file version 50, there will be StackMapTable attributes aiding the process by containing explicit type information, but only for code with branches. For sequential code, the type of variables still has to be derived by inference.
These inferred types are not necessarily the declared types. E.g., on the byte code level, there will be no difference between
CharSequence cs="foo";
cs.charAt(0);
and
String s="foo";
((CharSequence)s).charAt(0);
In both cases, there will be a storage of a String constant into a local variable followed by the invocation of an interface method. The inferred type will be String in both cases and the invocation of a CharSequence method considered valid as String implements CharSequence.
This disproves the idea of detecting that there is a local variable declared using the CharSequence (interface) type, as the actual declared type is irrelevant and not stored in the regular byte code.
There are, however, debugging attributes containing information about the local variables, see the LocalVariableTable attribute and libraries like ASM will tell you about the declarations if such information is present. But you can’t rely on these optional information. E.g. Oracle’s JRE libraries are by default shipped without them.
I don't sure I understood exacly what you want but .
you can use implement on each object ,
evry object that have getter you can implement it with class called getable .
and then you could do stuff only on object that have the function that you implement from the class getable .
https://docs.oracle.com/javase/tutorial/java/IandI/createinterface.html

Method Order in generated class file by javac

With JDK7, the reflection API has changed and now the methods returned by getDeclaredMethods() are not returned in the order in which they are declared in the source file.
Now my question is, does the .class file generated by javac contains methods in the same order in which they were defined in the source file OR it can write methods in random order too?
The Binary Compatibility chapter of the Java Language Specification is explicit about the fact that reordering of elements in the class files is permitted:
[...] here is a list of some important binary compatible changes that the Java programming language supports:
[...]
Reordering the fields, methods, or constructors in an existing type declaration.
[...]
Reordering the list of direct superinterfaces of a class or interface.
That means that the order in which they appear in the .class file is not dictated by the specifications. If you want to rely on it, you have to either (1) know for a fact that your specific implementation uses the same order as the definition order (testing it, like you've done, is a good idea but does not guarantee anything), or (2) change the order yourself.
Class.getDeclaredMethods API is clear about this "...The elements in the array returned are not sorted and are not in any particular order...". Most likely the reason of that is that javac is not obliged to generate methods in .class in any particular order.

How to access and read JVMs class file members?

I'm not very familiar with JVM and I have an assignment involving the Class file.
Write a java program that when run as
java DissectClassFile file1.class file2.class ...
it will print a summary of each class file as follows:
the name of the class defined by the class file,
its super class and interfaces it implements,
the number of items in the constant pool,
the number of interfaces implemented by the class, and their names,
the number of fields of the class whose name contain the underscore character,
the number of methods of the class whose names contain at least one capital letter
Right off the bat I don't know where to begin. If someone could help me out and point me in the correct direction, I should get the hang of it.
You need to read the Java Virtual Machine Specification. It contains an explanation of the class file format.
There is a class java.lang.Class to access that information. For every Class, you can call MyClass.class (for example, String.class) to get the object with the information for that class.
Most of this information can easily be gleaned loading each class using Class.forName(...) and using the reflection APIs to fish out the information. However the constant pool size is the killer. AFAIK, this can only be determined from the class file itself.
So, your options would seem to be:
Write a bunch of code to read and decode class files. The JVM spec has the details of the class file format.
Use an existing library such as BCEL to take care of the low-level class file parsing.
Use a hybrid of class file parsing (using either of the above) to extract the constant pool size, and the reflection APIs for the rest.
I imagine that your assignment hints at which way they expect you to go. But if not, I'd look at the BCEL approach first.

Dynamically create classes in Java

I would like to create a class in Java based on the fields defined in my XML config file:
For example: if the XML file contains (the syntax has been maligned for posting):
<property name="agent_host"></property>
<property name="subsystem"></property>
then internally it will create a class Event such as Event(String agentHost, String subSystem) that the client can instantiate. Note: the client always knows that this class will be called "Event" but does not know how many "mandatory parameters" it needs to pass.
On the other hand if I have a XML file with:
<property name="agent_host"></property>
then it will create Event(String eventHost) that the client can use for instantiation.
Yes, you could use reflection, but what comes to my mind is working with a class that you could add property.
Imagine a class that has one encapsulated HashMap using a String as a key (for the attribute name) and the value of the attribute so you could read the XML file and for evey property add the attribute to the class like.
For this line:
<property name="subsystem" type="String">value123</property>
GenericClass c = new GenericClass();
c.addAttribute("subsystem", new String("value123"));
//and you could implement a get and set methods like this:
public String getAttributeValue(String attributeName)
{
return internalHashMap.get(attributeName).toString();
}
Using this you could also implement a setAttributeValue
will be quite simple I think
If you really interested in creating a class dynamically, try Byte code Enhancement libraries like BCEL from Apache.
This isn't really a class you want, it's data. Why not use a hashmap? I really dislike "Bean" style classes--they encourage bad coding (there is no place in a generated class to put actual code, so everything ends up being manipulated by external code anyway).
You can just load a hashmap from your XML and inject it into a real object--that way you don't have to worry about actually passing a hash around, you are passing a real object with real business methods and real type safety--it just HAPPENS to use a hashmap internally to store data instead of member variables.
I've done a lot more than this, but at some point you realize Hibernate does everything you want for you.
I think the DynaBean from Commons-BeanUtils may be what you're looking for.
A DynaBean is a Java object that supports properties whose names and data types, as well as values, may be dynamically modified. To the maximum degree feasible, other components of the BeanUtils package will recognize such beans and treat them as standard JavaBeans for the purpose of retrieving and setting property values.

Obtaining Java source code from class name

Is there a way to obtain the Java source code from a class name?
For example, if I have access to the library with the class java.io.File, I want its source code.
I am working on a kind of parser and I need the source at execution time. I have also to search it recursively.
Say the aforementioned class has this method:
int method (User user) {...}
I would need to obtain User's source code, and so on and so forth with its inner classes.
Is there any way to obtain the java source from a class name? For example:...
You may want one of several possible solutions. Without knowing what you really want to do with the information, we can't be very precise with our recommendations, but I'd start by steering you away from source code if possible. JSE source code is available online, as are many open source libraries, but that may not always be the case. Additionally, you'll need to keep it all organized when you want to find it, much like a classpath, whereas the Class objects are much easier to get hold of, and manipulate, without having to parse text again.
Reflection
If you just need information about a class at runtime, just use the Java Reflection API. With it, given a Class object you can, for example, get the types of a specific field, list all fields and iterate over them, etc...:
Class clazz = User.class;
Field field = clazz.getDeclaredField("var");
System.out.println(field.getType().getName());
Reflection is useful for discovering information about the classes in the program, and of course you can walk the entire tree without having to find source code, or parse anything.
Remember you can lookup a class object (as long as it's on the classpath at runtime) with Class.forName("MyClass") and reflect on the resulting Class.
Bytecode Manipulation
If you need more than information, and actually want to manipulate the classes, you want bytecode manipulation. Some have tried to generate source code, compile to bytecode and load into their program, but trust me - using a solid bytecode manipulation API is far, far easier. I recommend ASM.
With it, you can not only get information about a class, but add new fields, new methods, create new classes... even load multiple variations of a class if you're feeling self-abusive. An example of using ASM can be found here.
Decompilation
If you really, really do need the source, and don't have it available, you can decompile it from a class object using one of the various decompilers out there. They use the same information and techniques as the above two, but go further and [attempt] to generate source code. Note that it doesn't always work. I recommend Jode, but a decent list, and comparison of others is available online.
File Lookup
If you have the source and really just want to look it up, maybe all you need is to put the .java files somewhere in a big tree, and retrieve based on package name as needed.
Class clazz = User.class;
String path = clazz.getPackage().getName().replaceAll("\\.","/");
File sourceFile = new File(path, clazz.getName() + ".java")
You want more logic there to check the class type, since obviously primatives don't have class definitions, and you want to handle array types differently.
You can lookup a class by name (if the .class files are on your classpath) with Class.forName("MyClass").
You can get a good approximation of the source from a class file using the JAVA decompiler of your choice. However, if you're really after the source of java.io.File then you can download that.
The best and simplest bet can be javap
hello.java
public class hello
{
public static void main(String[] args)
{
System.out.println("hello world!");
world();
}
static public void world()
{
System.out.println("I am second method");
}
}
do a javap hello and you will get this:
Compiled from "hello.java"
public class hello extends java.lang.Object{
public hello();
public static void main(java.lang.String[]);
public static void world();
}
Yes, if you download the source code. It's available for public download on the official download page.
If you're using Eclipse whenever you use the class you could right click > View Source (or simply click the class > F3) and it'll open a new tab with the source.
You can print the resource path from where the class was loaded with
URL sourceURL=obj.getClass().getProtectionDomain().getCodeSource().getLocation();
It will be a .class file , .jar,.zip, or something else.
So what you're trying to do is get the Java class at execution. For this, you need Java reflections.
If your goal is to get information about what's in a class, you may find the Java reflection API to be an easier approach. You can use reflection to look up the fields, methods, constructors, inheritance hierarchy, etc. of a class at runtime, without needing to have the source code for the class available.
Is there any way to obtain the java source from a class name?
The answer is complicated, not least because of the vagueness of your question. (Example notwithstanding).
In general it is not possible to get the real, actual Java source code for a class.
If you have (for example) a ZIP or JAR file containing the source code for the classes, then it is simple to extract the relevant source file based on the classes fully qualified name. But you have to have gotten those ZIP / JAR files from somewhere in the first place.
If you are only interested in method signatures, attribute names and types and so on, then much of this information is available at runtime using the Java reflection APIs. However, it depends on whether the classes were compiled with debug information (see the -g option to the javac compiler) how much will be available. And this is nowhere like the information that you can get from the real source code.
A decompiler may be able to generate compilable source code for a class from the bytecode files. But the decompiled code will look nothing like the original source code.
I guess, if you have a URL for a website populated with the javadocs for the classes, you could go from a class name, method name, or public attribute name to the corresponding javadoc URL at runtime. You could possibly even "screen scrape" the descriptions out of the javadocs. But once again, this is not the real source code.

Categories

Resources