harmony-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Tim Ellison <t.p.elli...@gmail.com>
Subject Re: [classlib][luni] String.toLowerCase/toUpperCase incorrect for supplementary characters (HARMONY-6649)
Date Fri, 24 Sep 2010 16:29:33 GMT
On 24/Sep/2010 17:08, Deven You wrote:
> It is a bit complex. First of all, I meet this problem because when I run
> specjbb benchmark, at the during of vm startup, it returned just the same
> error mentioned by Mohan.
> 
> Then I used java -verbose to show the boot classes load order, compared to
> harmony build between before this commit and after this commit and saw:
> before this commit, Locale is first loaded, and then ULocale loaded
> after this commit, ULocale is first loaded, and then Locale is loaded. this
> build will return the above NPE error.
> 
> Then I went on to check why with this commit, Locale won't be loaded before
> ULocale, I found before this commit,at the vm start up, CharsetProviderImpl
> will be invoked, it will invoke String.toUpperCase() which in turn invoke
> String.toUpperCase(Locale.getDefault()), at this point, Locale class will be
> loaded, and also at this point, there is no class used ULoclae yet, so
> ULocale is not loadede yet. And again at this point, Locale class will
> invoke ULocale class, so sequentially ULocale will be used thus loaded
> during Locale class init.
> 
> After with this commit, now CharsetPorviderImple will invoke its own
> toUpperCase() method which dose not depend on Locale class any longer, so at
> the point CharsetProviderImple is invoked, it dose not need Locale, so
> Locale class won't be loaded at this point.

The bit I was wondering about is this...

> Later for some reason, maybe other class need ULoclae, so ULocale is
> loaded.

We don't expose ULocale though our APIs, so it must be our own usage
that is causing this load.  I was wondering if you had found that first
reference, which would help us figure out the load sequence.

Regards,
Tim

> Again at that point, Locale
> class is still not loaded. With this condition, ULocale will invoke Locale
> methods, so Locale class will be loaded during ULocale class init. This
> cause Locale class is loaded after ULocale class.
> 
> Unfortunately, Current ULocale class will meet NPE  exception with above
> situation: Locale class is loaded after ULocale class. The root cause is
> that:
> ULocale class init will initialize below static field:
> public static final ULocale ENGLISH = new ULocale("en", Locale.ENGLISH);
> This cause Locale will be loaded, during Locale class init, below static
> field will be initialized:
>     public static final Locale CANADA = new Locale("en", "CA");
> new Locale("en", "CA"); will finally calls new ULocale(language, country,
> variant) and which will invoke getName(String localeID) and which will
> execute:
>        String name = nameCache.get(localeID), here, nameCache is a static
> field of ULocale, from above call sequence, we can see the ULocale class
>  just execute to initialize new ULocale("en", Locale.ENGLISH). It have no
> chance to initialze nameCache yet, so at this point, the java will throw NPE
> exception.
> 
> If Locale is loaded before ULocale, from Locale initialization process, the
> code logic and interaction mechanism between Locale and ULocale just by
> chance can avoid such situation and execute successfully.
> 
> I am not sure this is enough for you. Any unclear things please point out to
> me. Thanks a lot!
> 
> 
> 
> 
> 
>   From current Local and ULocale code logic. Locale class initialization
> process will call ULocale, it cause ULocal class init.
> 
> 2010/9/24 Tim Ellison <t.p.ellison@gmail.com>
> 
>> On 24/Sep/2010 08:17, Deven You wrote:
>>> I have saw the error before, and I have some investigation of it. I think
>>> the root cause is the commit change the class load order. Before this
>>> commit, Locale class will be loaded before ULocale class And after this
>>> commit, ULocale is loaded before Locale.
>> I'm not near the code right now so can you explain this to me please?
>> IIRC the Locale and ULocale are mutually dependent so will be loaded
>> together anyway. There is an 'early' initialization in Locale to set up
>> the US-en values for booting.
>>
>> So my question is where is the reference to ULocale being made earlier
>> now? and how did this change the behavior as it existed before.
>>
>> Regards,
>> Tim
>>
>>> The direct cause is CharsetProviderImpl no longer use String.toUpperCase,
>>> instead it uses its own toUpperCase.  And String.toUpperCase calls
>>> String.toUpperCase(Locale), this ensure Locale class will be loaded
>> before
>>> ULocale. However CharsetProviderImpl own toUpperCase uses no Locale, so
>> it
>>> causes Locale class loaded after ULocale.
>>>
>>> To solve this problem, a work around could simply be below:
>>> 1.Add a Locale static field in String:
>>> private static Locale defaulLocale = new Locale.getDefaultLocale();
>>> ...
>>> 2. Change the String.toUpperCase() from calling
>>> toUpperCase(Locale.getDefaultLocale()) to toUpperCase(defaultLocale)
>>>
>>> above change could solve the NullPointerException mentioned by Mohan, but
>> I
>>> am not sure if it is a good design.
>>>
>>> Caused by: java.lang.NullPointerException
>>>        at com.ibm.icu.util.ULocale.getName(ULocale.java:827)
>>>        at com.ibm.icu.util.ULocale.<init>(ULocale.java:480)
>>>        at java.util.Locale.<init>(Locale.java:228)
>>>        at java.util.Locale.<init>(Locale.java:201)
>>>        at java.util.Locale.<clinit>(Locale.java:51)
>>>        at com.ibm.icu.util.ULocale.<clinit>(ULocale.java:109)
>>>
>>>
>>>
>>>
>>>
>>> 2010/9/24 Mohanraj Loganathan <mohanraj.l@gmail.com>
>>>
>>>> On loading junit.jar[2] i get initialization exception[3]. This
>>>> exception disappears if i revert the patch committed for
>>>> (HARMONY-6649) toUpper/toLowerCase.
>>>>
>>>> Make sure your junit.jar contains the signature files[1]. (use the
>>>> junit.jar(version 3.8.2) bundled with eclipse).  So with HARMONY-6649
>>>> commit, I am not able to load the jar file if it's manifest contains
>>>> any signature related files. Any thought on this?
>>>>
>>>>
>>>> [1] jar -tvf junit.jar
>>>>  9714 Thu Aug 07 12:04:14 GMT+05:30 2008 META-INF/MANIFEST.MF
>>>>  9791 Thu Aug 07 12:04:14 GMT+05:30 2008 META-INF/ECLIPSE.SF
>>>>  3487 Thu Aug 07 12:04:14 GMT+05:30 2008 META-INF/ECLIPSE.RSA
>>>>     0 Fri Mar 03 15:22:26 GMT+05:30 2006 META-INF/
>>>>    76 Thu Aug 07 12:04:08 GMT+05:30 2008 META-INF/eclipse.inf
>>>>     0 Fri Mar 03 15:22:10 GMT+05:30 2006 junit/
>>>>     0 Fri Mar 03 15:22:26 GMT+05:30 2006 junit3.8.2/
>>>>     0 Fri Mar 03 15:22:24 GMT+05:30 2006 junit/awtui/
>>>>      ............
>>>>
>>>> [2] run command : java -cp junit.jar junit.textui.TestRunner
>>>>
>>>> [3] Exception:
>>>> Uncaught exception in main:
>>>> java.lang.ExceptionInInitializerError
>>>>        at com.ibm.icu.util.ULocale.<clinit>(ULocale.java:109)
>>>>        at
>>>> com.ibm.icu.impl.ICUResourceBundle.instantiateBundle(ICUResourceBundl
>>>> e.java:810)
>>>>        at
>>>> com.ibm.icu.impl.ICUResourceBundle.getBundleInstance(ICUResourceBundl
>>>> e.java:801)
>>>>        at
>>>> com.ibm.icu.util.UResourceBundle.getRootType(UResourceBundle.java:489
>>>> )
>>>>        at
>>>> com.ibm.icu.util.UResourceBundle.instantiateBundle(UResourceBundle.ja
>>>> va:536)
>>>>        at
>>>> com.ibm.icu.util.UResourceBundle.getBundleInstance(UResourceBundle.ja
>>>> va:144)
>>>>        at
>>>> com.ibm.icu.util.UResourceBundle.getBundleInstance(UResourceBundle.ja
>>>> va:124)
>>>>        at com.ibm.icu.impl.ZoneMeta.getSystemTimeZone(ZoneMeta.java:509)
>>>>        at com.ibm.icu.util.TimeZone.getTimeZone(TimeZone.java:617)
>>>>        at com.ibm.icu.util.TimeZone.getTimeZone(TimeZone.java:587)
>>>>        at java.util.SimpleTimeZone$1.run(SimpleTimeZone.java:50)
>>>>        at java.util.SimpleTimeZone$1.run(SimpleTimeZone.java:1)
>>>>        at
>>>> java.security.AccessController.doPrivilegedImpl(AccessController.java
>>>> :171)
>>>>        at
>>>> java.security.AccessController.doPrivileged(AccessController.java:53)
>>>>
>>>>        at
>> java.util.SimpleTimeZone.getICUTimeZone(SimpleTimeZone.java:48)
>>>>        at java.util.SimpleTimeZone.<init>(SimpleTimeZone.java:110)
>>>>        at java.util.TimeZone.<clinit>(TimeZone.java:91)
>>>>        at
>>>> org.apache.harmony.security.asn1.ASN1Time.getDecodedObject(ASN1Time.j
>>>> ava:51)
>>>>        at
>>>> org.apache.harmony.security.asn1.ASN1UTCTime.decode(ASN1UTCTime.java:
>>>> 96)
>>>>        at
>>>> org.apache.harmony.security.asn1.ASN1Choice.decode(ASN1Choice.java:32
>>>> 0)
>>>>        at
>>>> org.apache.harmony.security.asn1.BerInputStream.readSequence(BerInput
>>>> Stream.java:665)
>>>>        at
>>>> org.apache.harmony.security.asn1.DerInputStream.readSequence(DerInput
>>>> Stream.java:125)
>>>>        at
>>>> org.apache.harmony.security.asn1.ASN1Sequence.decode(ASN1Sequence.jav
>>>> a:48)
>>>>        at
>>>> org.apache.harmony.security.asn1.BerInputStream.readSequence(BerInput
>>>> Stream.java:665)
>>>>        at
>>>> org.apache.harmony.security.asn1.DerInputStream.readSequence(DerInput
>>>> Stream.java:125)
>>>>        at
>>>> org.apache.harmony.security.asn1.ASN1Sequence.decode(ASN1Sequence.jav
>>>> a:48)
>>>>        at
>>>> org.apache.harmony.security.asn1.BerInputStream.readSequence(BerInput
>>>> Stream.java:665)
>>>>        at
>>>> org.apache.harmony.security.asn1.DerInputStream.readSequence(DerInput
>>>> Stream.java:125)
>>>>        at
>>>> org.apache.harmony.security.asn1.ASN1Sequence.decode(ASN1Sequence.jav
>>>> a:48)
>>>>        at
>>>> org.apache.harmony.security.asn1.BerInputStream.decodeValueCollection
>>>> (BerInputStream.java:755)
>>>>        at
>>>> org.apache.harmony.security.asn1.BerInputStream.readSetOf(BerInputStr
>>>> eam.java:733)
>>>>        at
>>>> org.apache.harmony.security.asn1.DerInputStream.readSetOf(DerInputStr
>>>> eam.java:138)
>>>>        at
>>>> org.apache.harmony.security.asn1.ASN1SetOf.decode(ASN1SetOf.java:48)
>>>>        at
>>>> org.apache.harmony.security.asn1.ASN1Implicit.decode(ASN1Implicit.jav
>>>> a:140)
>>>>        at
>>>> org.apache.harmony.security.asn1.BerInputStream.readSequence(BerInput
>>>> Stream.java:665)
>>>>        at
>>>> org.apache.harmony.security.asn1.DerInputStream.readSequence(DerInput
>>>> Stream.java:125)
>>>>        at
>>>> org.apache.harmony.security.asn1.ASN1Sequence.decode(ASN1Sequence.jav
>>>> a:48)
>>>>        at
>>>> org.apache.harmony.security.asn1.ASN1Type.decode(ASN1Type.java:97)
>>>>        at
>>>> org.apache.harmony.security.pkcs7.ContentInfo$1.getDecodedObject(Cont
>>>> entInfo.java:153)
>>>>        at
>>>> org.apache.harmony.security.asn1.ASN1Sequence.decode(ASN1Sequence.jav
>>>> a:53)
>>>>        at
>>>> org.apache.harmony.security.utils.JarUtils.verifySignature(JarUtils.j
>>>> ava:73)
>>>>        at
>> java.util.jar.JarVerifier.verifyCertificate(JarVerifier.java:296)
>>>>        at
>> java.util.jar.JarVerifier.readCertificates(JarVerifier.java:265)
>>>>        at java.util.jar.JarFile.getInputStream(JarFile.java:392)
>>>>        at
>>>> java.net.URLClassLoader$URLJarHandler.createClass(URLClassLoader.java
>>>> :402)
>>>>        at
>>>> java.net.URLClassLoader$URLJarHandler.findClass(URLClassLoader.java:3
>>>> 71)
>>>>        at
>> java.net.URLClassLoader.findClassImpl(URLClassLoader.java:1209)
>>>>        at java.net.URLClassLoader$4.run(URLClassLoader.java:901)
>>>>        at java.net.URLClassLoader$4.run(URLClassLoader.java:1)
>>>>        at
>>>> java.security.AccessController.doPrivilegedImpl(AccessController.java
>>>> :171)
>>>>        at
>>>> java.security.AccessController.doPrivileged(AccessController.java:64)
>>>>
>>>>        at java.net.URLClassLoader.findClass(URLClassLoader.java:903)
>>>>        at java.lang.ClassLoader.loadClass(ClassLoader.java:488)
>>>>        at
>>>> java.lang.ClassLoader$SystemClassLoader.loadClass(ClassLoader.java:87
>>>> 0)
>>>>        at java.lang.ClassLoader.loadClass(ClassLoader.java:267)
>>>> Caused by: java.lang.NullPointerException
>>>>        at com.ibm.icu.util.ULocale.getName(ULocale.java:827)
>>>>        at com.ibm.icu.util.ULocale.<init>(ULocale.java:480)
>>>>        at java.util.Locale.<init>(Locale.java:228)
>>>>        at java.util.Locale.<init>(Locale.java:201)
>>>>        at java.util.Locale.<clinit>(Locale.java:51)
>>>>        at com.ibm.icu.util.ULocale.<clinit>(ULocale.java:109)
>>>>        ... 54 more
>>>> FAILED to invoke JVM.
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>> On Fri, Sep 24, 2010 at 11:57 AM, Tim Ellison <t.p.ellison@gmail.com>
>>>> wrote:
>>>>> On 24/Sep/2010 06:58, Robert Muir wrote:
>>>>>> On Fri, Sep 24, 2010 at 1:49 AM, Tim Ellison <t.p.ellison@gmail.com>
>>>> wrote:
>>>>>>> System.out.println(new File("σ.txt").hashCode());
>>>>>>> System.out.println(new File("ς.txt").hashCode());
>>>>>>>
>>>>>>> prints out
>>>>>>>
>>>>>>> 889962580
>>>>>>> 890776533
>>>>>>>
>>>>>>> on both Harmony and the RI.
>>>>>>>
>>>>>>>
>>>>>> but perhaps this is just a bug in the RI?
>>>>>> according to the link:
>>>>>>
>> http://download.oracle.com/javase/6/docs/api/java/io/File.html#hashCode%28%29
>>>>>> <
>> http://download.oracle.com/javase/6/docs/api/java/io/File.html#hashCode%28%29
>>>>> Because
>>>>>> equality of abstract pathnames is inherently system-dependent, so
is
>> the
>>>>>> computation of their hash codes.
>>>>>>
>>>>>> Is it a problem that "windows equals" is inconsistent with hashCode
>>>> here? I
>>>>>> admit these are corner cases.
>>>>> No, I don't think it is a problem.  I was reviewing the invokers of
>>>>> toLowerCase() and was confused by the wording in the spec.  I'm happy
>>>>> that we should simply lowercase it in a locale independent way, and
>>>>> don't need to do a "windows equals" implementation.
>>>>>
>>>>> Regards,
>>>>> Tim
>>>>>
>>>>
>>>> --
>>>> Mohan
>>>>
> 

Mime
View raw message