RFR: 8060130: Simplify the synchronization of defining and getting java.lang.Package

Peter Levart peter.levart at gmail.com
Mon Oct 13 15:15:26 UTC 2014


So we all came to same conclusions after all. I would call this a 
redundant concurrent "initialization" ;-)

Regards, Peter

On 10/13/2014 05:06 PM, Claes Redestad wrote:
> Hi Peter,
>
> On 10/13/2014 04:32 PM, Peter Levart wrote:
>> On 10/12/2014 04:09 AM, Claes Redestad wrote:
>>>
>>>
>>> http://cr.openjdk.java.net/~redestad/8060130/webrev.03/
>>>
>>
>> Hi Claes,
>>
>> First, one more nit:
>>
>> 1635                 if (!map.containsKey(pkgName)) {
>> 1636                     map.put(pkgName, pkg);
>> 1637                 }
>>
>> ..could be written as:
>>
>> map.putIfAbsent(pkgName, pkg);
>>
>
> Nice catch!
>
>>
>> And second, I re-read the code of CachedManifest and noticed the 
>> following. You initialize the volatile instance field 'manifest' like 
>> that:
>>
>>  609         private volatile Manifest manifest = EMPTY_MANIFEST;
>>
>>
>> So in following code:
>>
>>  631         public Manifest getManifest() {
>>  632             resolveManifest();
>>  633             return manifest;
>>  634         }
>>  635
>>  636         private void resolveManifest() {
>>  637             if (manifest != null || url == null) {
>>  638                 return;
>>  639             }
>>  640             synchronized(this) {
>>  641                 if (manifest == null) {
>>  642                     manifest = AccessController.doPrivileged(new 
>> PrivilegedAction<Manifest>() {
>>  643                         public Manifest run() {
>>  644                             return loadManifest(fileName);
>>  645                         }
>>  646                     });
>>  647                 }
>>  648             }
>>  649         }
>>
>>
>>
>> ... loadManifest() will never be executed. getManifest() will always 
>> return EMPTY_MANIFEST.
>>
>> You probably wanted line 637 to be written as:
>>
>> if (manivest != EMPTY_MANIFEST || url == null) { ...
>>
>>
>> Likewise in loadManifest(), wou write:
>>
>>  586     private static Manifest loadManifest(String fn) {
>>  587         try (FileInputStream fis = new FileInputStream(fn);
>>  588              JarInputStream jis = new JarInputStream(fis, false))
>>  589         {
>>  590             return jis.getManifest();
>>  591         } catch (IOException e) {
>>  592             return EMPTY_MANIFEST;
>>  593         }
>>  594     }
>>
>> ..but you probably wanted the line 592 to return 'null' instead.
>
> Yes, I realized I got this messed up and have prepared a new patch 
> which passes tests and includes your previous
> comments:
>
> http://cr.openjdk.java.net/~redestad/8060130/webrev.04
>
> Aleksey Shipilev pointed out offline that we can't trust the volatile 
> to be completely initialized here (requiring a
> null check either way), so the better solution is to initialize 
> manifest to null and set it to EMPTY_MANIFEST as
> we resolve and consistently only do null checks.
>
> Inlining resolveManifest and loadManifest into getManifest as you 
> suggested seems to get rid of a few generated
> access methods. It's cutting corners on line length limits, though, 
> but maybe it can be allowed in this case?
>
> By also moving the static final EMPTY_MANIFEST into CachedManifest we 
> avoid generating any access method for
> this as well, with no impact on readability.
>
> For reference I also did some java -verbose:class experiments: any 
> Hello World program will load most
> ConcurrentHashMap classes already - in the same order - and the new 
> inner class in j.l.Package won't be loaded
> unless the application goes to lengths to get a system package, so no 
> reordering of startup load order is to be
> expected. The deviant is getPackages, which when invoked will 
> additionally load a couple of ConcurrentHashMap
> traversal related classes, but I don't think that matters.
>
> Byte code size and complexity seems to drop a bit, too, if anyone's 
> counting:
>
> javap -v java.lang.Package | wc -l
> before: 1263, after: 1139
>
> javap -v java.lang.ClassLoader | wc -l
> before: 2800, after: 2687
>
> Thanks!
>
> /Claes
>
>>
>>
>> Regards, Peter
>>
>




More information about the core-libs-dev mailing list