RFR: 8273581: Change the mechanism by which JDK loads the platform-specific FontManager class [v3]

Sergey Bylokhov serb at openjdk.java.net
Mon Sep 20 17:02:14 UTC 2021


On Mon, 20 Sep 2021 16:55:49 GMT, Brett Okken <github.com+2996845+bokken at openjdk.org> wrote:

>> I wrote a simple example which uses DLC and lazy initialization holder class idioms. The FontManager is only created when it is accessed the first time via the getInstance() method in both cases and they both fail if an exception is thrown during the class initialization.
>> 
>> Is the problem with Holder idiom that it throws `ExceptionInInitializerError` which contains the original exception as the cause whereas with DLC the original exception is directly thrown?
>> 
>> public class FontManagerFactory {
>> 
>>     private static volatile FontManager instance;
>> 
>>     public static FontManager getInstanceDLC() {
>> 
>>         FontManager result = instance;
>>         if (result == null) {
>>             synchronized (FontManagerFactory.class) {
>>                 result = instance;
>>                 if (result == null) {
>>                     instance = result = new FontManager("One", "Two", "Three");
>>                 }
>>             }
>>         }
>>         return result;
>>     }
>> 
>>     public static FontManager getInstanceHolder() {
>>         return FontManagerHolder.instance;
>>     }
>> 
>> 
>>     public static void main(String[] args) {
>>         String lazyInitializationIdiom = args[0];
>>         System.out.printf("Use lazy initialization idiom: %s%n", lazyInitializationIdiom);
>>         if ("DLC".equals(args[0])) {
>>             System.out.printf("DLC FontManager instance: %s%n", getInstanceDLC());
>>         } else if ("Holder".equals(args[0])) {
>>             System.out.printf("Lazy Initialization Holder FontManager instance: %s%n", getInstanceHolder());
>>         }
>>     }
>> 
>>     private static class FontManagerHolder {
>>         private static final FontManager instance = new FontManager("One", "Two", "Three");
>>     }
>> }
>> 
>> class FontManager {
>>     public FontManager(String... args) {
>>         System.out.println(args[5]);
>>     }
>> }
>> ``` 
>> DLC:
>> 
>> java FontManagerFactory DLC
>> Use lazy initialization idiom: DLC
>> Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 5 out of bounds for length 3
>> 	at FontManager.<init>(FontManagerFactory.java:41)
>> 	at FontManagerFactory.getInstanceDLC(FontManagerFactory.java:12)
>> 	at FontManagerFactory.main(FontManagerFactory.java:28)
>> 
>> Hodler:
>> 
>> java FontManagerFactory Holder
>> Use lazy initialization idiom: Holder
>> Exception in thread "main" java.lang.ExceptionInInitializerError
>> 	at FontManagerFactory.getInstanceHolder(FontManagerFactory.java:20)
>> 	at FontManagerFactory.main(FontManagerFactory.java:30)
>> Caused by: java.lang.ArrayIndexOutOfBoundsException: Index 5 out of bounds for length 3
>> 	at FontManager.<init>(FontManagerFactory.java:41)
>> 	at FontManagerFactory$FontManagerHolder.<clinit>(FontManagerFactory.java:35)
>> 	... 2 more
>
> Does that stack trace difference really matter?
> if so, you could wrap the `return FontManagerHolder.instance;` in a try/catch that throws that caused by:
> 
> 
> try {
>   return FontManagerHolder.instance;
> } catch (java.lang.ExceptionInInitializerError e) {
>   final Throwable cause = e.getCause();
>   if (cause instanceof RuntimeException re) {
>     throw re;
>   }
>   //could wrap in IllegalStateException or just throw the error
> }
> 
> 
> If this getInstance method is called with any frequency, getting rid of the volatile access each time is a nice bonus.

The difference is that Holder will fail that way forever, while the DLC have a chance to resurrect on next call.

-------------

PR: https://git.openjdk.java.net/jdk/pull/5517



More information about the client-libs-dev mailing list