Class.forName Bytecode Transformation Investigation
Brian Goetz
brian.goetz at oracle.com
Wed Sep 28 16:59:03 UTC 2022
One possible compatibility issue is the exceptions that may be thrown.
Have we done a review to compare the exceptions thrown by Class::forName
vs the substituted code?
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
> <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/78499eb2/attachment.htm>
More information about the leyden-dev
mailing list