@Documented
@Target(value={CONSTRUCTOR,METHOD,FIELD})
@Retention(value=CLASS)
public @interface GwtRetention
This annotation allows you to do two things:
asyncOnly() tells the gwt compiler that the annotated
type or member should only be loaded in the classloader-only split point.
dependencies() tells the compiler to include external dependencies
whenever the given type or member is included.
This gives you the power to defer code bloat into one big ball of code that will not affect your application bootsrap timing. It also allows you to declare reflection retention on classes you do not control, so you don't have to have an unmaintainable mess of copies of source code just to add your reflection retention annotations.
When you annotate a member (method, field or constructor), it's dependencies
will be added when that member is included (currently when the class is loaded,
but work is being done for more fine-grained inclusion).
If the member is deferred to the com.google.gwt.reflect.client.ConstPool split point,
so are its dependencies. If loaded synchronously (asyncOnly()=false),
it is included when the enclosing type is sent through GwtReflect.magicClass(Class),
or when you directly access that member as a CONSTANT-ONLY reference:
SomeClass.class.getField("constantName");// includes dependencies on that field
SomeClass.class.getMethod("constantName", CONSTANT_CLASS_ARRAY);// array must be a constant field.
SomeClass.class.getDeclaredMethods();// includes all dependencies of all declared methods.
Support for the full level of declared optimizations is not yet complete, but this annotation will be used to define more complex strategies for retaining reflective access to runtime types and members.
With great power comes great responsibility: Misuse of Retention policies may lead to code bloat, and cause your application more code than is necessary to perform its given duty.
That said, this does give you the power to directly control what code gets loaded where, so if you know you want to include a given snippet of code in a given code split, this will allow you to specify members you want to include now, but call later on.
If you need to pull code of non-exclusive or leftover code blocks, this annotation will allow you to pull specific code into an exclusive code block, and reduce clinits() in your non-exclusive code blocks.
| Modifier and Type | Fields and Description |
|---|---|
static int |
ALL |
static int |
PACKAGE |
static int |
PRIVATE |
static int |
PROTECTED |
static int |
PUBLIC |
| Modifier and Type | Optional Element and Description |
|---|---|
int |
annotationRetention
If you want to keep your parameter annotations, you must set this member to true
|
boolean |
asyncOnly
This element will only be included in the monolithic ClassLoader.
|
Dependency[] |
dependencies
Any additional dependencies to declare?
|
boolean |
keepParameterAnnotations
If you want to keep your parameter annotations, you must set this member to true
|
boolean |
keepPublicSuperMembers
This option is only valid when
GwtRetention is placed inside
a class or package level ReflectionStrategy. |
int |
privacy
An int register of the privacy level of members to keep.
|
public abstract int privacy
Use this to filter out unneeded members and reduce code size.
Set to 0 to elide members.
This will allow you to do strange things, like only keep public and private; really, whatever filter you want to reduce your compile size (just be careful!)
public abstract boolean asyncOnly
This will allow you to defer things you "want later", and only
include what you need now behind a call to
GwtReflect#getClassloader(com.google.gwt.user.client.rpc.AsyncCallback).
Future work is planned to build a preprocessor which checks against unused reflection objects, and pulls those references out of the main application, and into the classloader.
In anticipation of this optimization, do try to prefer the "most constant possible" manner of retrieving your reflection data.
BEST: SomeClass.class.getMethod("someConstantString", String.class, int[].class);
GOOD: SomeClass.class.getMethod(SOME_CONSTANT_STRING, SOME_CONSTANT_CLASS_ARRAY);
OKAY: Class c = GwtReflect.magicClass(SomeClass.class); c.getMethod(...);
BAD: Method[] methods = GwtReflect.magicClass(SomeClass.class).getMethods();
WORST: for (Method method : GwtReflect.magicClass(SomeClass.class).getMethods())
if (isMethodIWant(method)) doSomething(method);
In order for this to work right, we will have to scan your ast for all calls into reflection methods, and pull out anything unused into the classloader code block. If we are unable to determine a minimum bounds for data needed in a class, we will have to include it all immediately.
Any element which explicitly uses classLoaderOnly() will always be deferred, and you should get in the habit of explicitly declaring this, as it will make scanning either easier, or entirely unnecessary.
Once the deferment optimization is complete, a maven mojo will be provided that can simply scan your gwt module, ignore all existing @GwtRetention annotations, and auto annotate all elements with the most optimal retention levels possible.
public abstract boolean keepPublicSuperMembers
GwtRetention is placed inside
a class or package level ReflectionStrategy.
It tells the compiler whether or not to search super types for public members of the given member type.
This defaults to true so out-of-the-box behavior matches that of JVM reflection. You may want to set it to false to reduce code size; just remember to always access members by their declaring class),
public abstract int annotationRetention
If it is a common request to keep complete jvm parity, this default might change, so there is no harm in explicitly setting it to false when you are trimming code bloat.
public abstract boolean keepParameterAnnotations
If it is a common request to keep complete jvm parity, this default might change, so there is no harm in explicitly setting it to false when you are trimming code bloat.
public abstract Dependency[] dependencies
Add them to a GwtRetention annotation, and instead of explicitly overriding and maintaining a copy of classes you don't control, just add @Dependencies to a type you do control, and use it to declare when and where you want to include the given dependency.
Be sure to read the doc on GwtRetention to see the
best practices for using this somewhat dangerous tool.
If you are using complex retention strategies, you should run emma (and story-of-your-compile) to check your code coverage and see if you can refine your strategy to keep code bloat down.