Class.forName Bytecode Transformation Investigation

Sonia Zaldana Calles szaldana at redhat.com
Wed Sep 28 18:01:32 UTC 2022


Hi Brian,

That’s a great catch. We need to ensure we are preserving the meaning of
the code and the plugin is not removing dead exception handlers. I’ll look
into this.


Thanks,

Sonia


On Wed, Sep 28, 2022 at 1:28 PM Brian Goetz <brian.goetz at oracle.com> wrote:

> Does your plugin eliminate dead reflective exception handlers?  If the
> class is known to be in the image, then we can not only transform
> Class::forName, but handling of attendant CNFE as well.  In:
>
>     try {
>         c = Class.forName("blah");
>     }
>     catch (CFNE ce) { /* stuff */ }
>
> the catch handler is also dead if the class is known to be in the image.
>
> On 9/28/2022 11:51 AM, Sonia Zaldana Calles wrote:
>
> Hi folks,
>
> In line with Dan’s previous investigation on bytecode transformations to
> modify Java’s dynamic behaviour, I have created a ClassForName JLink Plugin
> which translates the reflective operation Class.forName
> <https://docs.oracle.com/javase/8/docs/api/java/lang/Class.html#forName-java.lang.String->
> to the ldc bytecode instruction using the ASM <https://asm.ow2.io/>
> library.
>
> The bytecode transformation switches out calls to Class.forName to ldc
> instructions for classes that are statically known, along with addressing
> the mismatch between Class.forName, which initialises the class by default,
> and ldc, which does not, by using MethodHandles.Lookup.ensureInitialized
> <https://docs.oracle.com/en/java/javase/19/docs/api/java.base/java/lang/invoke/MethodHandles.Lookup.html#ensureInitialized(java.lang.Class)>
> .
>
> For example, the bytecode sequence
> Class.forName(“com.sonia.hello.HelloWorld”) is transformed as shown below:
>
> Original:
>
> 0: ldc           #7                  // String com.sonia.hello.HelloWorld
>
> 2: invokestatic  #9                  // Method
> java/lang/Class.forName:(Ljava/lang/String;)Ljava/lang/Class;
>
> Transformed:
>
> 0: invokestatic  #43 // Method
> java/lang/invoke/MethodHandles.lookup:()Ljava/lang/invoke/MethodHandles$Lookup;
>
> 3: ldc           #45                 // class com/sonia/hello/HelloWorld
>
> 5: invokevirtual #51 // Method
> java/lang/invoke/MethodHandles$Lookup.ensureInitialized:(Ljava/lang/Class;)Ljava/lang/Class;
>
>
> The plugin supports configuring two modes: global and module-aware. The
> module mode transforms Class.forName calls only when accessing a class
> accessible to the current module per the module graph, while the global
> mode transforms all classes regardless of readability. Note, class
> accessibility is determined per the JVMS 5.4.4
> <http://cr.openjdk.java.net/~iris/se/18/latestSpec/java-se-18-jvms-fr-diffs.pdf>
> - a class must be public, its module must be read by the current class’s
> module and its package must be exported to the current class’s module.
> There are slight differences between the language’s and the VM’s view of
> accessibility.
>
> We have also introduced an internal plugin called ModuleGraphPlugin which
> creates a single logical view of the module graph. This plugin separates
> the logic determining class readability and is queried by the ClassForName
> plugin to drive transformations. It doesn’t require further configuration
> from users as it is configured by default when using the ClassForName
> plugin.
>
> The ModuleGraphPlugin was separated out as it allows other plugins to
> share a common view of the module graph without needing to have each plugin
> process the module-info.java files.
>
> While a Class.forName JLink plugin previously existed (and was removed),
> it was limited to modifications within a module as it didn’t have the
> ModuleGraphPlugin-awareness of the full module graph.
>
> We don’t expect any performance improvement from this change itself, but
> we are expecting it to increase the ability of other future plugins to
> reason about application behaviour and to potentially help remove
> reflective operations in other contexts.
>
> Find below the GitHub link with the changes:
>
> https://github.com/SoniaZaldana/jdk-sandbox/tree/classforname-plugin
>
>
> Thanks,
>
> Sonia
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/leyden-dev/attachments/20220928/4d097e4a/attachment.htm>


More information about the leyden-dev mailing list