How to create synthetic fields in java?

2019-04-06 12:00发布

问题:

  1. How can synthetic fields be created in Java?

  2. Can synthetic fields in java only be created at runtime? If not: Is there a standard-compliant way to this at compile time (without changing some bytes in the class file)

回答1:

They're created by the compiler when "oddities" of the language require them. A simple example of this is using an inner class:

public class Test
{
    class Inner
    {
    }
}

The Test.Inner class will have a synthetic field to represent the appropriate instance of the Test class.

We can extend this code slightly to show that field:

import java.lang.reflect.*;

public class Test
{
    public static void main(String[] args)
    {
        for (Field field : Inner.class.getDeclaredFields())
        {
            System.out.println(field.getName() + ": " + field.isSynthetic());
        }
    }

    class Inner
    {
    }
}

With my compiler, that prints:

this$0: true


回答2:

Yes, it's doable, and it's called load-time weaving. Essentially, you will need to define your own ClassLoader that will decide on a class-by-class case whether to do modify a classfile that is bout to be loaded; that means you will need to inspect the binary class that is being loaded, possibly modify it, then pass it on to the JVM for definition/resolving. It's a bit cumbersome, complicated, and prone to ClassCastExceptions (the same class defined in 2 different classloaders will give 2 different classes that are not assignment-compatible).

Note that weaving allows you to do much more: you can add new methods, interfaces, fields, modify the code of existing classes, and more.

There are already tools that can help you - see for example AspectJ as a full-on language modification, or something like BCEL or javassist that allows you to write such weaving tools.