Let's say I have this class:
#Annotate class MyClass {
MyField field = new MyField(params);
}
How can I get the initializing part of my class field when I process my annotation (the new MyField(params) part)?
I can't see anything related in the FieldDeclaration class.
You can't.
Whether you use reflection or apt, you cannot access code blocks.
Through apt you can access anything you can annotate, but you can't annotate initializer blocks (although you could access an annotated local variable inside an initializer block).
Through reflection there is no way to access code blocks (only Constructors, Fields, Methods and Classes)
If you are desperate enough about this, you need to use a source parser like javaparser or a byte code tool like asm. Both understand tree structures (the former uses source trees, the latter byte code trees) and can deal with all java structures, including initializer blocks.
But your best bet is probably AspectJ and it's initialization(ConstructorSignature) pointcut. There is some reference on the pointcuts page but to really grasp it you would probably have to read AspectJ in Action by Ramnivas Laddad.
Related
Hello StackOverflow Community,
I recently discovered Java Instrumentation and what great things you can do with it, so I decided to write a small library for me that simplifies some of these things.
I have the following method (simplified):
public static void editClass(Class<*> clazz) {
...
}
It adds a transformer via Instrumentation that transforms the bytecode of loaded classes with the name of clazz.getName().
So in my premain method, I can say
editClass(Foo.class);
My problem is, by specifying the class via a reference to it (.class), this class gets loaded before the transformer is added, so after that, I have to retransform the class which prevents me from adding/removing methods and so on.
So, is there a way to not load the class when using this class reference? Or an other way to implement this? I know that I could just pass the class name as an argument, but I would really like to make this whole library type-safe and make refactoring easier.
Thanks in advance!
If you want to call the editClass method from premain only and we assume that the Java Agent itself does not use the class otherwise, so that the class literal inside the editClass call would be the only trigger, you can do the following:
provide both methods, editClass(Class<?> clazz) and editClass(String qualifiedName)
write the premain method (or agent classes in general) using editClass(Class<?>) and enjoy compile-time safety regarding the existence of the classes referenced via literals
perform a static code transformation of the agent classes, replacing all calls of editClass(Class<?>) with editClass(String)
This shouldn’t be too hard, as you only have to replace all sequences of ldc packagename/Foo.class, invokestatic (Ljava/lang/Class;)V with ldc "packagename.Foo", invokestatic (Ljava/lang/String;)V.
It may become even easier when the method editClass(String qualifiedName) can handle the internal class names (using slashes instead of dots).
Since you said you “recently discovered Java Instrumentation”, this might be a good exercise in class file transformations
Use the transformed Agent classes which have no references to the classes to transform anymore, to perform the load time transformations
I recently read this article by Jake Wharton. This is targeted at Android, but also perfectly valid for java I think.
Consider the following code:
public class A {
private String someField = "abc";
class B {
public void doSomething() {
System.out.println(someField);
}
}
}
We have a simple class A and an inner class B (This has a reference to A and can acccess its members). Class B is accessing the field someField in A even though it is private. According to the article, this is done by the compiler generating synthetic accessor methods which allow the inner class to access the field.
Now my way more basic question: Why does the compiler even care about visiblities when the code is compiled? As we have seen in this example, a new method is generated, which basically just introduces overhead.
Visibilities are a great thing for architecting good software, but if the compiler is done checking that everything is correct according to the declared visibilies, why not optimize those methods away (E.g. just taking everything for being public and allow calls to it)?
First I thought this was due to security reasons, but reflection allows the access of all fields, not caring for visibility as far as I know.
This might be a basic misunderstanding of me, if so, I would be happy if someone could explain it to me.
Why does the compiler even care about visiblities when the code is compiled?
The JVM doesn't allows access to private methods/constructors/fields outside a class. It has no special rule for nested classes which were added after this rule was designed. Instead the compiler adds accessor methods so the language can support a means of access the JVM doesn't.
As we have seen in this example, a new method is generated, which basically just introduces overhead.
Only if the method isn't called very much and isn't optimised.
Adding any simple method (On Hotspot, any method of 35 bytes or less) will be inlined very quickly and has no impact on performance (except if the maximum inline level is reached)
why not optimize those methods away
It does this at runtime so that previous rules continue to be enforced.
reflection allows the access of all fields, not caring for visibility as far as I know.
Though not by default, you have to explicitly want this as an option and not have a SecurityManager which prevents it.
If compiler converts all private fields to public fields in compile time, one problem will be happened when your project is compiled into library and reused by others. In that case, all your private fields will become public.
There are some tools for optimizing this. In Android, there is a tool named ProGuard that will convert all getter/setter to direct field access.
I am wondering if it would be possible to generate a class, via an annotation processor, that would be an inner class of a class to be compiled.
For instance, while compiling class A, generate class A$Foo. I wonder if there is a trick that could be used or not. I got the feeling that it might be possible to generate some source that will be compiled in the same byte code as an inner class would. And, at compile/runtime, the JVM would take it for an inner class, and allow accessing outer class private fields.
The idea behind that question, which is not a noobie question, though it may look more or less technical, is to be able to use the private visibility modifier for annotated fields like Dagger, ButterKnife, etc. The private modifier allowing to detect unused fields more easily, whereas package private protection hides them.
Or is there any workaround, any way to get the best of both words ?
Given your use case, no.
An inner class is a normal Java class, living in a different .class file. When compiled, a hidden constructor param is added to the inner class constructor. Private fields in the outer class are made accessible by adding hidden accessor methods in the outer class. All of this happens at compile time.
The JVM has nothing to do with that. If you generate a class that "looks like an inner class of another class", that won't make the outer class fields accessible.
Private visibility is really just a hint to compiler. There is no problem to access those fields at the runtime at all (like I do in my small dependency injector: https://github.com/ko5tik/andject)
And non-static inner classes on android are generally a bad idea as it used to have performance penalty.
At the compile time you could use source generation tool like xdoclet (though it became technically obsolete years ago, but still occasionally used) and generate all the sources you need in advance before compiling them.
It is common in Java classes to have lots of getter and setter methods, one each for every data model class variable. I realize that many IDEs will create these for you, but I'm trying to avoid this clutter and not have all these methods in my classes. So, is there any way to access a variable in a read only fashion outside the class (as if it were public final), while retaining write access inside the class or subclass exclusively (as if it were private or protected).
The only pseudo-solution I've come up with is a base class (or interface with default methods) that has a get(String variableName) method which then gets the fields of the class via reflection and returns the appropriate one. The downside is that for that to work, the variables have to be public, so only by convention does it meet my requirements (in that in the extending/implementing class that has the variables I want to access, I only call the get method from outside the class, and don't implement a set method). The main thing I don't like about this is that if a variable name changes, callers of the get methods will not cause compiler errors, since the variable name is just a hardcoded String.
Anyone have a better idea?
Yes - try to design your classes so you don't have getters and setters at all. Typically it's a bad design to have getters and setters on all of your fields because it breaks encapsulation. An exception is the case of Java Beans (where you have a model class/DTO or some class that's mapped to XML/JSON); here you should not mind them because setters and getters are the only methods.
In classes that have logic, inject your dependencies via constructor or directly if you use Spring/CDI and you like it. This is more safe because you won't have objects in inconsistent states; like for example you create an object but forget to call a setter -> NullPointerException. But by using constructors, you avoid the case of forgetting to call the setters.
Of course there might be exceptions, like when setting some optional fields when you don't want all the dependencies in the constructor all the time. This however can be solved with overloading constructors or if the case is more complex the problem can be solved in a more elegant way by using the builder pattern.
See a great article on this: http://www.javaworld.com/article/2073723/core-java/why-getter-and-setter-methods-are-evil.html
You may use lombok - to manually avoid getter and setter method. But it create by itself.
The using of lombok significantly reduces a lot number of code. I found it pretty fine and easy to use. But here you may find some pros and cons of using lombok here.
Hope it will help.
Thanks a lot.
Java FX introduced something similar to what you want: ReadOnlyProperty
Might not be exactly what you are looking for, though. In general, I don't think exposing a variable is a good idea.
I'm familiar with various ways of intercepting method invocations using proxies, but I'm wondering if there's a way to detect field access / dereferences on some proxy using a library like Javassist or ASM? For example:
void detectFieldName(Function<Foo, Supplier<String>> f) {
Foo fooProxy = createFooProxy();
f.apply(fooProxy);
}
detectFieldName((Foo foo) -> foo.bar);
Ideally from this I'd like to know that a field named bar was dereferenced.
Looking at your updated use case: lambdas are desugared to synthetic (compiler-generated) methods, with a function object that forwards interface calls through the generated method (I haven't looked into exactly how this is implemented, but I think Brian Goetz has talked about it). You can just look in that method's bytecode (loaded from the class file; some of the ASM sample code does this) and read off the field access. Instrumentation is not required.
Note that you can't create a proxy to see field access; the field access is performed in the lambda method (or more generally, where the field is loaded) without executing any code in Foo. In fact, you don't even need to call the lambda if all you want is to get the field name, and if all you're using the Foo proxy for is the call, you don't need a proxy.
I'm not aware of any way to intercept field accesses as easily as java.lang.reflect.Proxy makes intercepting method calls.
The getfield and putfield bytecodes use symbolic descriptors that encode the class and field name, so you could use a Java agent to add method calls before or after each load and store passing the field name, object and value being loaded/stored. (This works best if you're only interested in a subset of fields, say all fields of a particular class.) Depending on your needs, you may also have to recognize reflective accesses to your fields by instrumenting use of java.lang.reflect.Field, the handle returned by MethodHandles.Lookup.findGetter/Setter etc. (which may involve interprocedural analysis or reasoning about string operations used to build the field name, etc.). You could also try instrumenting "just before" the library calls into some JVM-specific native functionality, but that ties you to one JVM implementation and your instrumentation may be skipped if the JVM intrinsifies (special-cases codegen for) reflective calls.
If you're willing to write C code, you can use the JVM Tool Interface watched field functions. This seems the easiest way to get information, but it's harder to do interesting Java-level things with (though you can call back into your Java support library from the JVMTI).
Without major hacks, this is not possible. Field access in Java is not bound dynamically. This means, any reading or writing to a field is hardcoded into all using classes. With a method proxy, one makes use of the fact you can override a method to determine behavior. For intercepting field access, one would need to intercept the class that is using a field. Some libraries emulate this behavior by replacing field access by synthetic accessor methods. This requires however some build time redefinition of all concerned classes throughout the entire project.
As for your example, you could in theory use a tool like ASM to extract the required information from the lambda expression. However, note that the lambda expression's code will be extracted into a method of the class of the method that uses the lambda expression. You might have trouble finding out which method it actually is that contains your lambda but the byte code for invoking the expression will merely look something like this:
InvokeDynamic #0:accept:(LFoo;)Ljava/util/function/Function;
As you can see, the byte code will only contain a possibly ambiguous signature. Otherwise, you could of course copy the lambda expression's logic into a new class where you changed the logic of a field access. Since lambdas are by definition interfaces, the creation of such a new class would actually be comparably easy. But the problem with the method detection remains.