I'm currently working on a Java library and I want to add some public static final String fields using bytecode manipulation which just hold some info about an entity. e.g.Customer.TABLE_NAME. I want to be able to access these fields before compile time while writing code something like what lombok allows you to do. Obviously those lombok generated methods don't actually exist before the code has been compiled but we can still see and use them without any problem. How can I achieve something like this?
Have you looked into AspectJ inter-type declarations (ITD)? They do exactly what you need. Of course, you can also use more low-level tools like Byte Buddy and Javassist or really low level ones like ASM in order to achieve the same.
Most of those tools can be used during the build process, transforming your class files, or alternatively as Java agents, i.e. they perform the byte code transformation during class-loading. It depends on your use case. If I understand correctly, your use case is that other developers using your classes can see the additional fields or methods you create dynamically. In that case, you would add them during build time and they would be part of the byte code in your library or module.
Related
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. :)
Is it possible to use a bytecode manipulation library like ASM at compile time?
Specifically, I'd like to use Java's annotation processing API to implement boilerplate-heavy methods on annotated classes. Implementing an annotation processor is straightforward enough, but it seems like the .class files don't yet exist when the Processor is run. Is there another way?
You might be interested in Javassist ( http://www.jboss.org/javassist ) which can enhance and save classes as a post-compilation step.
This article describes how to save enhanced classes : https://dzone.com/articles/implementing-build-time
in particular, once you have altered a class, you can do something like this:
compiledClass.writeFile("/tmp/modifiedClassesFolder");
It should be possible since the following project is doing it: Project Lombok
Also:
Java 8 will bring a new mechanism that allows you to write plug-ins for the Java compiler (javac). A compiler plug-in lets you add new phases to javac without making changes to its code base. New behavior can be encapsulated in a plug-in and distributed for other people to use. For example, javac plug-ins could be used to do the following:
• Add extra compile-time checks
• Add code transformations
• Perform customized analysis of source code
You should use CGLib instead. With CGLib you can add proxies with method interceptors and have the interceptor implement your boilerplate code. Another option is to look at Javassist. With Javassist you literally create a new subclass using actual text (in strings) and have javassist compile it into byte-code.
I'm looking for a possibility to load the Java code dynamically into a
class at the run time. The Java Code should be readed from an
XML-file. There are just some "If-Then" expressions and should be
added into one class and use it like any other class in my project.
Actually my file contains some rule codes which i want to load like cache and use
this class further
Does someone know if it is possible in java?
best regards
Abhij
I believe you can do this with CGLib, but I haven't done more than use it to mock classes at runtime. If dynamic code is a major aspect of your application you should consider using a language like Ruby which has much better support for running code read in at runtime.
I'm trying to identify places where annotation names are the same or similar to compile a list of these things to make sure our team knows where possible points of confusion can be found. For example, Guice #provides and RESTeasy #provider are similar enough in spelling but different enough in semantics as to confuse people so I'd like to call that out explicitly and explain the differences.
What I'm looking for is a tool or even a website that enumerates the annotations associated with packages. This might be a pipe dream, but before I manually start going through and collecting these things I thought I'd check.
I was considering writing one based on Javadoc that simply only pulled in the annotations but I don't have access to Java source files in many cases.
Any thoughts or suggestions?
In Eclipse you can use the standard method "Search for references" (context menu of a used annotation References -> Project) and you are getting a list where the annotations is used within your project.
I suggest to scan for annotations yourself and generate a list for that.
You can do that by writing your own implementation of an annotation processer, i.e. extend AbstractProcessor. Within this processor you can write a text file containing all Annotations. You can add this processor to your build procedure, then it will execute the processor when you build the project.
Another way to do this is using the Google Reflections library. This might be a bit more work since you would need to write a small programm to fetch the annotations and write the file.
I wrote such a tool: https://github.com/MoserMichael/ls-annotations
it decompiles the byte code and lists declarations (classes, functions, variables) with annotations only. You can also use it to find all classes/interfaces derived from a given class/inerface - and all the classes/interfaces derived from a given class/interface.
The tool uses the asm library to scan class files and to extract annotations. it can detect annotations with retention policy CLASS and RUNTIME. It can't detect annotations with retention policy SOURCE that are not put into bytecode, for example #Override is one of these.
Why not scanning your classpath and export all used annotations? Then just use some simple parsing / text compare to see the elements with almost the same name?
I have a post-compilation step that manipulates the Java bytecode of generated classes. I'd like to make life as painless as possible for library consumers, so I'm looking at ways I can make this process automatic and (if possible) compiler agnostic.
The Annotation Processing API provides many of the desired features (automatic service discovery; supported by Eclipse). Unfortunately, this is aimed at code generators and doesn't support manipulation of existing artefacts:
The initial inputs to the tool are
considered to be created by the zeroth
round; therefore, attempting to create
a source or class file corresponding
to one of those inputs will result in
a FilerException.
The Decorator pattern recommended by the API is not an option.
I can see how to perform the step with a runtime agent/instrumentation, but this is a worse option than a manual build step as it would require anyone even peripherally touched by the API to configure their JVMs in a non-obvious manner.
Is there a way to plug into or wrap the compiler tool as invoked by javac? Has anyone successfully subverted the annotation processors to manipulate bytecode, no matter what the doc says?
The Groovy compiler is the only bytecode compiler which allows to hook into the compilation process (example: Generate bytecode to support the Singleton pattern)
The Annotation Processing API is not meant to change the code. As you have already found out, all you can do is install a classloader, examine the bytecode at runtime and manipulate it. It's braindead but it works. This follows the general "we're afraid that a developer could try something stupid" theme which you will find throughout Java. There is no way to extend javac. The relevant classes are either private, final or will change with the next version of Java.
Another option is to write annotated Java, for example you write a class "ExampleTpl.java". Then, you use a precompiler which expands the annotations in that file to get "Example.java". In the rest of the code, you use Example and ignore ExampleTpl.
For Eclipse, there is a bug report to automate this step. I'm not aware of any other work in this area.
It can be done.
Take a look at my blog post Roman Numerals, in our Java where an annotation processor is used to rewrite code. Limitation being that it works with Sun's javac only.