How can I access a java compile time parameter at runtime? - java

We are migrating a system written in C to Java and must retain existing processes (no debate). We currently "embed" compile-time information into the C application using the C preprocessor, for example:
cc -o xxx.o -DCOMP_ARG='"compile time arg"' xxx.c
The xxx.c file can then use "COMP_ARG" and its value will be embedded in the code and we have little worry about it being changed inadvertently.
We realize Java likes to use properties files, however, our requirements are such that some information ** ** be embedded in the code, so properties files are not an option - these certain values cannot be specified at runtime. To illustrate the point, such data could be a date-stamp of when the file was compiled, but the exact data is irrelevant to the question.
We are looking for a way to specify at compile time various values that are available to the Java code. We are quite aware that Java does not have a pre-processor as does C, so the mechanism would be different.
Our current solution is using a code generation step (Maven), which does work, however, Eclipse is wreaking havoc trying to deal with the source files so that we had turn off "Build Automatically". We really want to find a more robust solution.
We appreciate any help, thanks.

The xxx.c file can then use "COMP_ARG" and its value will be embedded
in the code and we have little worry about it being changed
inadvertently.
...our requirements are such that some information be embedded in the
code....
We are looking for a way to specify at compile time various values
that are available to the Java code. We are quite aware that Java does
not have a pre-processor as does C, so the mechanism would be
different.
It seems that the best way to solve this problem would be to make use of annotations in your code.
In Java, annotations are a kind of interface declaration, but they do not enforce a behavioral contract with an implementing class. Rather, they are meant to define a contract with some external framework, preprocessor, or with the compiler itself. Annotations are used extensively in Java EE 5.0 (and later) to specify configuration and behavior to the framework within which the developer's code runs. Annotations are also used extensively by the JavaDoc documentation processor. Here, the annotations in the doc comments allow you to specify and format the information which you intend to appear in the documentation when the JavaDoc processor runs.
Annotations can be defined to be accessible at runtime. In such a case, the primary mechanism for accessing annotations is the Java Reflection facility. For example, annotations with a retention policy of RUNTIME and defined on a class, can be accessed through that class's corresponding Class object:
Class myCls = MyClass.class; // the "class literal" for MyClass
Annotation[] annotations = myCls.getDeclaredAnnotations();
Annotations can include arguments for parameters to allow for more flexibility in configuration. The use of annotations is most convenient when the code itself can be so annotated.
A quick tutorial on how annotations are defined and used in Java is available here: https://docs.oracle.com/javase/tutorial/java/annotations/

I'm going to post my own answer which seems to be "Can't be done" - what can't be done, apparently, is provide at compile time to Java, a set of parameters that gets passed to the program at execution time. The solution appears to be to continue with what I am doing which is to update a Java source file with the compile-time data and figure out how to coax Eclipse to stop over-writing the files.
Thanks to everyone who commented.

Related

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

Providing Dummy-Annotation for older Java compilers

I'm working on a Java library that I would like to be able to use across a couple of different Java compiler versions. Some annotations (specifically #SafeVarargs) only exist on some of these compiler versions and generate errors in others.
Especially for something like #SafeVarargs, which serves mostly as a marker to suppress warnings rather than actually changing the output of the compiler, I would like to be able to use these annotations and simply provide a dummy-implementation if an earlier compiler is missing them.
How would I go about doing this?
I guess you could just create surrogate implementations of those annotations and put them in a Jar that is added to the classpath making sure that the system/compiler provided one take priority when resolved by the corresponding class loader.
For example you can just copy the code of SafeVarargs from here

How is AOP being implemented to Change Java interface content?

I am current using Seasar2 Framework on a project that I am in. The framework is quite popular here in Japan but I am having problem in finding English documentations. Even on their official English translation site, they just discuss that the framework use Dependency Injection and AOP.
I was intrigued with the way they use it in one of their component S2Dao. Basically you only need to create interface DAO class and the framework automatically, changes the code on runtime and creates intermediate class that get called in the middle. Hence DB transactions codes are automatically added to the class. I was wondering, is there any step by step explanation on how this is done? Can java change code on runtime and change the method on runtime?
Are good reference on how this is done? I just want to know how the framework is doing this.
Yes, it is possible to do dynamic implementations of an interface at runtime, and to manipulate the compiled bytecode also.
Java provides a built-in mechanism to implement interfaces at run-time, called dynamic proxy classes.
There are also good libraries like cglib or javassist, that allow you not only to implement interfaces, but also to extend classes and to manipulate bytecode at run-time (to change the behavior of a method, for example). Frameworks like Spring and Hibernate use libraries like these to make their magic, so your framework may be using some of these also.
NOTE: If you are curious, these libraries can "tweak" the bytecode because instead of using the default ClassLoader of the JVM, they load your classes using their own ClassLoader, so they have total control of every single byte of the loaded class, and they can do whatever they want with them :).

Tool to identify Java annotations in various Java APIs

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?

Plugging in to Java compilers

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.

Categories