From masayoshi.okutsu at oracle.com Mon Aug 1 02:14:03 2016 From: masayoshi.okutsu at oracle.com (Masayoshi Okutsu) Date: Mon, 1 Aug 2016 11:14:03 +0900 Subject: Review Request : JDK-8066652 : Default TimeZone is GMT not local if user.timezone is invalid on Mac OS In-Reply-To: <00c25acdf99440609c3d10ee426dede7@DEWDFE13DE11.global.corp.sap> References: <66d02394-289b-5fe0-6d7c-b7a65d2491f7@oracle.com> <5acc8b7b9b9c4d9a821d24cc4003199b@DEWDFE13DE11.global.corp.sap> <00c25acdf99440609c3d10ee426dede7@DEWDFE13DE11.global.corp.sap> Message-ID: +1 Masayoshi On 8/1/2016 6:40 AM, Langer, Christoph wrote: > Thanks Rachna, that's fine now :) > >> -----Original Message----- >> From: i18n-dev [mailto:i18n-dev-bounces at openjdk.java.net] On Behalf Of >> Rachna Goel >> Sent: Sonntag, 31. Juli 2016 19:47 >> To: i18n-dev at openjdk.java.net >> Subject: Re: Review Request : JDK-8066652 : Default TimeZone is >> GMT not local if user.timezone is invalid on Mac OS >> >> Hi, >> >> Thanks for the review. >> Please have a look at updated web rev at : >> >> http://cr.openjdk.java.net/~rgoel/JDK-8066652/webrev.02/ >> >> >> Thanks, >> Rachna >> >>> On Jul 29, 2016, at 4:35 PM, Langer, Christoph >> wrote: >>> Hi Rachna, >>> >>> In general, the fix looks good to me. >>> >>> However, there are a few indentation flaws, in lines 830, 831 and 834 - 841. >> Please make sure you use 4 chars indentation. >>> And you should remove the blank between the cast to (time_t) and the >> variable in line 832. >>> Also, please note that I'm no reviewer. >>> >>> Best regards, >>> Christoph >>> >>>> -----Original Message----- >>>> From: i18n-dev [mailto:i18n-dev-bounces at openjdk.java.net] On Behalf Of >>>> Rachna Goel >>>> Sent: Freitag, 29. Juli 2016 08:17 >>>> To: i18n-dev at openjdk.java.net >>>> Subject: Review Request : JDK-8066652 : Default TimeZone is >> GMT >>>> not local if user.timezone is invalid on Mac OS >>>> >>>> Hi, >>>> >>>> Please review the fix for JDK-8066652. >>>> >>>> Bug : https://bugs.openjdk.java.net/browse/JDK-8066652 >>>> >>>> Webrev: http://cr.openjdk.java.net/~rgoel/JDK-8066652/webrev.01/ >>>> >>>> Fix : 1. Used thread safe function localtime_r() to retrieve system >>>> timezone. >>>> 2. timezone retrieved should be "GMT" if system timezone is >>>> "GMT" and user specifies a fake timezone using user.timezone system >>>> property. >>>> Earlier it used to be "GMT+00:00" which is wrong. >>>> >>>> -- >>>> Thanks, >>>> Rachna From nishit.jain at oracle.com Mon Aug 1 08:56:05 2016 From: nishit.jain at oracle.com (Nishit Jain) Date: Mon, 1 Aug 2016 14:26:05 +0530 Subject: Review Request for JDK-7153347: System read/stat/open calls should be hardened to handle EINTR Message-ID: <9a006af4-5a28-dee4-4f0d-360573c48cd0@oracle.com> Hi, Please review the fix for JDK-7153347 Bug: https://bugs.openjdk.java.net/browse/JDK-7153347 Webrev: http://cr.openjdk.java.net/~nishjain/7153347/webrev.01/ Fix: Handled the signal (EINTR) interrupt during the native stat/fstat/lstat/read/open function call using RESTARTABLE macro. Regards, Nishit Jain From peter.levart at gmail.com Mon Aug 1 14:10:26 2016 From: peter.levart at gmail.com (Peter Levart) Date: Mon, 1 Aug 2016 16:10:26 +0200 Subject: RFR: 8161203: ResourceBundle.getBundle performance regression In-Reply-To: <2b8eb9f2-7b81-512b-6dde-0631d2c01c39@oracle.com> References: <7fc61181-7c3c-ea1c-d07a-90a2e712844c@oracle.com> <5991183a-8d2a-967d-74ec-c99e7d1636f3@oracle.com> <884a78a8-ebfb-a15d-a036-37b9fd377401@gmail.com> <2b8eb9f2-7b81-512b-6dde-0631d2c01c39@oracle.com> Message-ID: <4826d920-0ec2-5f97-5266-c53458ff779b@gmail.com> Hi Masayosh, Alan, Thanks for looking at the change. I suppose application containers are already accustomed to invoke ResourceBundle.clearCache(ClassLoader) when undeploying an application so that the corresponding ClassLoader can get GCed right away. But there's a change in the semantics of this method that Jigsaw introduced... Before Jigsaw, this method was specified to: * Removes all resource bundles from the cache that have been loaded * using the given class loader. After Jigsaw, this method is specified to: * Removes all resource bundles from the cache that have been loaded * by the caller's module using the given class loader. Now suppose that the "caller's module" that loads the bundle is the application's module and the module that clears the cache is the container's module. The app's cache won't get cleared. I understand that the change in semantics was an attempt to "isolate" modules among themselves so that one module could not clear the cache of another module if they happen to map to the same class loader, but this also means that an application container can't easily clear the cache of the application it wishes to undeploy unless it uses the new ResourceBundle.clearCache(Module) method on each application's module before undeploying it. I also wonder if the change of the semantics of this method is backwards compatible. Suppose that some container is using this method to clear the cache of the application loaded by say "classloaderA" before undeploying it. It calls ResourceBundle.clearCache(classloaderA). Now suppose the container code is loaded by some other class loader (say "classloaderC") which is usually the case in today's containers. Both container and application classes are part of the unnamed modules of their corresponding class loaders. With the change in the semantics of this method introduced by jigsaw, the container will not clear the cache of the application any more since the container module is not the same as the application module (they are distinct unnamed modules). Anyway, I noticed an inconsistency in my webrev.04 immediately after posting it a week ago. I was off for a week then, so now that I'm back, here's the corrected webrev of my proposed change: http://cr.openjdk.java.net/~plevart/jdk9-dev/ResourceBundle.cleanup/webrev.05/ The only real change of logic compared to webrev.04 is that I moved the "format" field from the LoadSession (previous CacheKey) to ResourceBundle itself. This field is needed to hold the bundle's format for invoking the Control.needsReload() method. It is not semantically correct to use the value from the LoadSession as done in webrev.04. This has to be the value that the bundle was created with, so it belongs to the bundle itself. In original code it was taken from the cloned CacheKey that was attached to the bundle. All other changes from webrev.04 are limited to ResourceBundle.java file and include some comments and nits that don't change the overall logic. All ResourceBundle tests still pass. The diff from webrev.04 is the following: *** ResourceBundle.webrev.04.java 2016-08-01 15:33:49.408565452 +0200 --- ResourceBundle.java 2016-08-01 14:43:59.875401697 +0200 *************** *** 40,55 **** package java.util; - import jdk.internal.misc.JavaUtilResourceBundleAccess; - import jdk.internal.misc.SharedSecrets; - import jdk.internal.reflect.CallerSensitive; - import jdk.internal.reflect.Reflection; - import jdk.internal.util.concurrent.AbstractClassLoaderValue; - import jdk.internal.util.concurrent.ClassLoaderValue; - import sun.util.locale.BaseLocale; - import sun.util.locale.LocaleObjectCache; - import sun.util.locale.provider.ResourceBundleProviderSupport; - import java.io.IOException; import java.io.InputStream; import java.lang.ref.ReferenceQueue; --- 40,45 ---- *************** *** 69,74 **** --- 59,73 ---- import java.util.spi.ResourceBundleControlProvider; import java.util.spi.ResourceBundleProvider; + import jdk.internal.misc.JavaUtilResourceBundleAccess; + import jdk.internal.misc.SharedSecrets; + import jdk.internal.reflect.CallerSensitive; + import jdk.internal.reflect.Reflection; + import jdk.internal.util.concurrent.AbstractClassLoaderValue; + import jdk.internal.util.concurrent.ClassLoaderValue; + import sun.util.locale.BaseLocale; + import sun.util.locale.LocaleObjectCache; + import sun.util.locale.provider.ResourceBundleProviderSupport; import static sun.security.util.SecurityConstants.GET_CLASSLOADER_PERMISSION; *************** *** 346,354 **** */ public abstract class ResourceBundle { - /** initial size of the bundle cache */ - private static final int INITIAL_CACHE_SIZE = 32; - static { SharedSecrets.setJavaUtilResourceBundleAccess( new JavaUtilResourceBundleAccess() { --- 345,350 ---- *************** *** 386,392 **** /** ! * The cache of BundleReference(s) per class loader, bundle base name and locale. */ private static final ClassLoaderValue cache = new ClassLoaderValue<>(); --- 382,389 ---- /** ! * The cache of BundleReference(s) per class loader, module, bundle base name ! * and locale. */ private static final ClassLoaderValue cache = new ClassLoaderValue<>(); *************** *** 419,430 **** * The parent bundle is searched by {@link #getObject getObject} * when this bundle does not contain a particular resource. */ ! protected ResourceBundle parent = null; /** * The locale for this bundle. */ ! private Locale locale = null; /** * The base bundle name for this bundle. --- 416,427 ---- * The parent bundle is searched by {@link #getObject getObject} * when this bundle does not contain a particular resource. */ ! protected ResourceBundle parent; /** * The locale for this bundle. */ ! private Locale locale; /** * The base bundle name for this bundle. *************** *** 432,437 **** --- 429,440 ---- private String name; /** + * Bundle format which is necessary for calling + * Control.needsReload(). + */ + private String format; + + /** * The flag indicating this bundle has expired in the cache. */ private volatile boolean expired; *************** *** 622,629 **** /** * A session object used during the {@link #getBundle} call. ! * The loader may be null, but the base name, the locale and ! * module must have a non-null value. */ private static class LoadSession { // These four are the actual keys for lookup in cache. --- 625,633 ---- /** * A session object used during the {@link #getBundle} call. ! * The loader may be null (in which case it is considered to be the ! * bootstrap class loader), but the module, base name, and locale must have ! * a non-null value. */ private static class LoadSession { // These four are the actual keys for lookup in cache. *************** *** 642,651 **** return key().get(loader); } - // bundle format which is necessary for calling - // Control.needsReload(). - private String format; - // Placeholder for an error report by a Throwable private Throwable cause; --- 646,651 ---- *************** *** 699,712 **** return callerHasProvider == Boolean.TRUE; } - String getFormat() { - return format; - } - - void setFormat(String format) { - this.format = format; - } - private void setCause(Throwable cause) { if (this.cause == null) { this.cause = cause; --- 699,704 ---- *************** *** 734,740 **** } } return "LookupSession[" + name + ", lc=" + l + ", ldr=" + getLoader() ! + "(format=" + format + ")]"; } } --- 726,732 ---- } } return "LookupSession[" + name + ", lc=" + l + ", ldr=" + getLoader() ! + "]"; } } *************** *** 1666,1672 **** bundle = loadBundleFromProviders(baseName, targetLocale, providers, loadSession); if (bundle != null) { ! loadSession.setFormat(UNKNOWN_FORMAT); } } // If none of providers returned a bundle and the caller has no provider, --- 1658,1664 ---- bundle = loadBundleFromProviders(baseName, targetLocale, providers, loadSession); if (bundle != null) { ! bundle.format = UNKNOWN_FORMAT; } } // If none of providers returned a bundle and the caller has no provider, *************** *** 1690,1696 **** } if (bundle != null) { ! loadSession.setFormat(format); break; } } catch (Exception e) { --- 1682,1688 ---- } if (bundle != null) { ! bundle.format = format; break; } } catch (Exception e) { *************** *** 1764,1770 **** Iterable providers, LoadSession loadSession) { ! // assert cacheKey != null && providers != null; return AccessController.doPrivileged( new PrivilegedAction<>() { public ResourceBundle run() { --- 1756,1762 ---- Iterable providers, LoadSession loadSession) { ! // assert loadSession != null && providers != null; return AccessController.doPrivileged( new PrivilegedAction<>() { public ResourceBundle run() { *************** *** 1819,1825 **** if (bundle != null) { // Set the format in the cache key so that it can be // used when calling needsReload later. ! loadSession.setFormat(format); bundle.name = loadSession.getName(); bundle.locale = targetLocale; // Bundle provider might reuse instances. So we should make --- 1811,1817 ---- if (bundle != null) { // Set the format in the cache key so that it can be // used when calling needsReload later. ! bundle.format = format; bundle.name = loadSession.getName(); bundle.locale = targetLocale; // Bundle provider might reuse instances. So we should make *************** *** 1877,1883 **** * Finds a bundle in the cache. Any expired bundles are marked as * `expired' and removed from the cache upon return. * ! * @param loadSession the key to look up the cache * @param control the Control to be used for the expiration control * @return the cached bundle, or null if the bundle is not found in the * cache or its parent has expired. bundle.expire is true --- 1869,1875 ---- * Finds a bundle in the cache. Any expired bundles are marked as * `expired' and removed from the cache upon return. * ! * @param loadSession the load session used look up the cache * @param control the Control to be used for the expiration control * @return the cached bundle, or null if the bundle is not found in the * cache or its parent has expired. bundle.expire is true *************** *** 1946,1954 **** if (!bundle.expired && expirationTime >= 0 && expirationTime <= System.currentTimeMillis()) { try { ! bundle.expired = control.needsReload(loadSession.getName(), ! loadSession.getLocale(), ! loadSession.getFormat(), loadSession.getLoader(), bundle, bundle.loadTime); --- 1938,1946 ---- if (!bundle.expired && expirationTime >= 0 && expirationTime <= System.currentTimeMillis()) { try { ! bundle.expired = control.needsReload(bundle.getBaseBundleName(), ! bundle.getLocale(), ! bundle.format, loadSession.getLoader(), bundle, bundle.loadTime); In my opinion, the change of the semantics of ResourceBundle.clearCache(ClassLoader) could be tolerated if the invocation of that method was not a requirement for application containers to be able to unload the app's class loader. With my proposed change to caching it is not a requirement any more. Regards, Peter On 07/25/2016 08:08 AM, Masayoshi Okutsu wrote: > Hi Peter, > > The change (ResourceBundle part) looks very good to me. There's a > simple workaround for the problem -- call > ResourceBundle.clearCache(ClassLoader). So I don't know how serious > the problem is, though. I still like this change. > > Yes, the comment in ReferenceTest should be removed. > > Thanks, > Masayoshi > > On 7/22/2016 10:13 PM, Peter Levart wrote: >> On 07/22/2016 10:46 AM, Peter Levart wrote: >>> Hi Masayoshi, >> >> Here's a preview of work to migrate ResourceBundle caching to using >> ClassLoaderValue utility: >> >> http://cr.openjdk.java.net/~plevart/jdk9-dev/ResourceBundle.cleanup/webrev.04/ >> >> >> The changes are very straightforward. They preserve the general >> structure of the logic. I renamed the CacheKey nested class to >> LoadSession as it now only functions as a mutable object passed >> around the methods while executing the getBundle() process. >> LoadSession is now a factory for ClassLoaderValue cache key. I moved >> the loadTime and expirationTime fields from LoadSession (old >> CacheKey) to ResourceBundle. As each cached entry must maintain it's >> own loadTime/expirationTime, I changed the NONEXISTENT_BUNDLE >> constant into a private subclass of ResourceBundle. The back-link >> from ResourceBundle to CacheKey is not needed any more. There is a >> backlink from BundleReference to ClassLoaderValue key and the >> associated ClassLoader to enable expunging. >> >> All 41 java/util/ResourceBundle tests pass with this change applied. >> Including the ReferenceTest which I had to modify a little to remove >> a dependency on ResourceBundle.cacheList field which is only used in >> test to report the size of the Map. It is not possible to obtain the >> size of the Map any more with this change applied, since the entries >> are distributed to multiple Map(s) - one Map per ClassLoader >> instance. The following comment in ReferenceTest could now be removed: >> >> * This test relies on the current behavior of the garbage collector >> and is >> * therefore no clear indicator of whether the fix for 4405807 works. >> * If the test fails, it might indicate a regression, or it might >> just mean >> * that a less aggressive garbage collector is used. >> >> ...as the ClassLoader(s) unloading does not depend on eagerness of >> SoftReference(s) clearing or any other activity any more. >> >> What do you think? >> >> Regards, Peter >> >>> >>> Thinking of how the ResourceBundle caching is implemented, I think >>> it has a serious flaw. The cache is currently the following: >>> >>> private static final ConcurrentMap cacheList >>> >>> ...where the CacheKey is an object which contains WeakReference(s) >>> to the caller's ClassLoader and Module. This is OK. >>> >>> BundleReference, OTOH, is a SoftReference. The >>> problem is ResourceBundle(s) can be arbitrary user subclasses, which >>> means that they may have an implicit reference to the ClassLoader >>> that appears in the CacheKey. The consequence is that such cache can >>> prevent GC-ing of the ClassLoader for arbitrary amount of time >>> (SoftReferences are cleared on memory pressure). >>> >>> Luckily there might be a solution. If the ResourceBundle subclasses >>> are always resolvable from the ClassLoader that appears in the >>> CacheKey, then there is a utility class that I created recently: >>> java.lang.reflect.ClassLoaderValue. This a package-private class as >>> it is currently used only in java.lang.reflect.Proxy for caching of >>> dynamic Proxy classes, but could be made public and moved to some >>> jdk.internal... package. >>> >>> Basing ResourceBundle caching on this utility class could also >>> simplify the implementation as you wouldn't have to deal with >>> WeakReference(s) to ClassLoader and Module objects. You could still >>> have a BundleReference extending SoftReference to >>> release the bundles on memory pressure but since such >>> SoftReference(s) would be anchored in the particular ClassLoader >>> instance that can resolve the ResourceBundle subclasses, it would >>> not prevent such ClassLoader from being GCed immediately. >>> >>> I can prototype such caching if you like. >>> >>> Regards, Peter >>> >>> On 07/22/2016 06:07 AM, Masayoshi Okutsu wrote: >>>> Hi Peter, >>>> >>>> Thank you for your suggestion. Actually CacheKey is used for >>>> storing information required to load resource bundles during a >>>> ResourceBundle.getBundle call. The current CacheKey usage may be >>>> too tricky and cause some maintenance problems. I will file a >>>> separate issue on that problem. I wanted to work on some clean up >>>> of the CacheKey usage, but I haven't had a chance. >>>> >>>> Thanks, >>>> Masayoshi >>>> >>>> >>>> On 7/21/2016 10:13 PM, Peter Levart wrote: >>>>> Hi Masayoshi, >>>>> >>>>> Previously the CacheKey::clone() method cleared a reference to >>>>> 'providers' in the clone making the provides unreachable from the >>>>> clone and making the clone unable to obtain providers. Now you >>>>> also reset the 'providersChecked' flag which makes the clone be >>>>> able to re-obtain the providers. This is dangerous as the clone is >>>>> used as a key in the cache and is strongly reachable from the >>>>> cache. A slight future modification of code could unintentionally >>>>> produce a class loader leak. To prevent that, I would somehow mark >>>>> the clone so that any attempt to invoke getProviders() on the >>>>> clone would throw IllegalStateException. >>>>> >>>>> Regards, Peter >>>>> >>>>> On 07/21/2016 06:14 AM, Masayoshi Okutsu wrote: >>>>>> Hi, >>>>>> >>>>>> Please review the fix for JDK-8161203. The fix is to lazily load >>>>>> ResourceBundleProviders. It's not necessary to load providers >>>>>> before cache look-up. >>>>>> >>>>>> Issue: >>>>>> https://bugs.openjdk.java.net/browse/JDK-8161203 >>>>>> >>>>>> Webrev: >>>>>> http://cr.openjdk.java.net/~okutsu/9/8161203/webrev.01 >>>>>> >>>>>> Thanks, >>>>>> Masayoshi >>>>>> >>>>> >>>> >>> >> > From christoph.langer at sap.com Mon Aug 1 14:47:57 2016 From: christoph.langer at sap.com (Langer, Christoph) Date: Mon, 1 Aug 2016 14:47:57 +0000 Subject: Review Request for JDK-7153347: System read/stat/open calls should be hardened to handle EINTR In-Reply-To: <9a006af4-5a28-dee4-4f0d-360573c48cd0@oracle.com> References: <9a006af4-5a28-dee4-4f0d-360573c48cd0@oracle.com> Message-ID: <9938a3a1589f4597aa0c1e4bda8d51f0@DEWDFE13DE11.global.corp.sap> Hi Nishit, this looks good and aligns with other places which were hardened for EINTR. But I'm not a reviewer, so you need to get a higher vote, still :) Best regards Christoph > -----Original Message----- > From: i18n-dev [mailto:i18n-dev-bounces at openjdk.java.net] On Behalf Of > Nishit Jain > Sent: Montag, 1. August 2016 10:56 > To: i18n-dev at openjdk.java.net > Subject: Review Request for JDK-7153347: System read/stat/open > calls should be hardened to handle EINTR > > Hi, > > Please review the fix for JDK-7153347 > > Bug: https://bugs.openjdk.java.net/browse/JDK-7153347 > Webrev: http://cr.openjdk.java.net/~nishjain/7153347/webrev.01/ > > Fix: Handled the signal (EINTR) interrupt during the native > stat/fstat/lstat/read/open function call using RESTARTABLE macro. > > Regards, > Nishit Jain From masayoshi.okutsu at oracle.com Mon Aug 1 23:27:34 2016 From: masayoshi.okutsu at oracle.com (Masayoshi Okutsu) Date: Tue, 2 Aug 2016 08:27:34 +0900 Subject: Review Request for JDK-7153347: System read/stat/open calls should be hardened to handle EINTR In-Reply-To: <9938a3a1589f4597aa0c1e4bda8d51f0@DEWDFE13DE11.global.corp.sap> References: <9a006af4-5a28-dee4-4f0d-360573c48cd0@oracle.com> <9938a3a1589f4597aa0c1e4bda8d51f0@DEWDFE13DE11.global.corp.sap> Message-ID: +1 Masayoshi On 8/1/2016 11:47 PM, Langer, Christoph wrote: > Hi Nishit, > > this looks good and aligns with other places which were hardened for EINTR. > > But I'm not a reviewer, so you need to get a higher vote, still :) > > Best regards > Christoph > >> -----Original Message----- >> From: i18n-dev [mailto:i18n-dev-bounces at openjdk.java.net] On Behalf Of >> Nishit Jain >> Sent: Montag, 1. August 2016 10:56 >> To: i18n-dev at openjdk.java.net >> Subject: Review Request for JDK-7153347: System read/stat/open >> calls should be hardened to handle EINTR >> >> Hi, >> >> Please review the fix for JDK-7153347 >> >> Bug: https://bugs.openjdk.java.net/browse/JDK-7153347 >> Webrev: http://cr.openjdk.java.net/~nishjain/7153347/webrev.01/ >> >> Fix: Handled the signal (EINTR) interrupt during the native >> stat/fstat/lstat/read/open function call using RESTARTABLE macro. >> >> Regards, >> Nishit Jain From nishit.jain at oracle.com Tue Aug 2 05:53:02 2016 From: nishit.jain at oracle.com (Nishit Jain) Date: Tue, 2 Aug 2016 11:23:02 +0530 Subject: Review Request for JDK-8035133: Locale matching: Weight q=0 isn't handled correctly. Message-ID: <21ceeb5f-1fd1-89d8-f6bc-f8fcf1df40a6@oracle.com> Hi, Please review the fix for JDK-8035133 Bug: https://bugs.openjdk.java.net/browse/JDK-8035133 Webrev: http://cr.openjdk.java.net/~nishjain/8035133/webrev.03/ Fix: Changed the filter and lookup mechanism to eliminate the matching tags which are falling in the specified exclusion range i.e. the range specified with quality weight 0 (q=0). The mechanism to handle q=0 was not there in the previous implementation. Regards, Nishit Jain From masayoshi.okutsu at oracle.com Tue Aug 2 15:30:42 2016 From: masayoshi.okutsu at oracle.com (Masayoshi Okutsu) Date: Wed, 3 Aug 2016 00:30:42 +0900 Subject: RFR: 8161203: ResourceBundle.getBundle performance regression In-Reply-To: <4826d920-0ec2-5f97-5266-c53458ff779b@gmail.com> References: <7fc61181-7c3c-ea1c-d07a-90a2e712844c@oracle.com> <5991183a-8d2a-967d-74ec-c99e7d1636f3@oracle.com> <884a78a8-ebfb-a15d-a036-37b9fd377401@gmail.com> <2b8eb9f2-7b81-512b-6dde-0631d2c01c39@oracle.com> <4826d920-0ec2-5f97-5266-c53458ff779b@gmail.com> Message-ID: <0e19e8ab-570e-f9d6-4602-dee90adf213e@oracle.com> Hi Peter, Thanks for bringing up the semantics issue of clearCache. You are right. There's some semantics change in clearCache(ClassLoader). Let me look into it. The format field-related changes look good to me. Thanks, Masayoshi On 8/1/2016 11:10 PM, Peter Levart wrote: > Hi Masayosh, Alan, > > Thanks for looking at the change. > > I suppose application containers are already accustomed to invoke > ResourceBundle.clearCache(ClassLoader) when undeploying an application > so that the corresponding ClassLoader can get GCed right away. But > there's a change in the semantics of this method that Jigsaw > introduced... > > Before Jigsaw, this method was specified to: > > * Removes all resource bundles from the cache that have been loaded > * using the given class loader. > > After Jigsaw, this method is specified to: > > * Removes all resource bundles from the cache that have been loaded > * by the caller's module using the given class loader. > > > Now suppose that the "caller's module" that loads the bundle is the > application's module and the module that clears the cache is the > container's module. The app's cache won't get cleared. I understand > that the change in semantics was an attempt to "isolate" modules among > themselves so that one module could not clear the cache of another > module if they happen to map to the same class loader, but this also > means that an application container can't easily clear the cache of > the application it wishes to undeploy unless it uses the new > ResourceBundle.clearCache(Module) method on each application's module > before undeploying it. > > I also wonder if the change of the semantics of this method is > backwards compatible. Suppose that some container is using this method > to clear the cache of the application loaded by say "classloaderA" > before undeploying it. It calls > ResourceBundle.clearCache(classloaderA). Now suppose the container > code is loaded by some other class loader (say "classloaderC") which > is usually the case in today's containers. Both container and > application classes are part of the unnamed modules of their > corresponding class loaders. With the change in the semantics of this > method introduced by jigsaw, the container will not clear the cache of > the application any more since the container module is not the same as > the application module (they are distinct unnamed modules). > > Anyway, I noticed an inconsistency in my webrev.04 immediately after > posting it a week ago. I was off for a week then, so now that I'm > back, here's the corrected webrev of my proposed change: > > http://cr.openjdk.java.net/~plevart/jdk9-dev/ResourceBundle.cleanup/webrev.05/ > > > The only real change of logic compared to webrev.04 is that I moved > the "format" field from the LoadSession (previous CacheKey) to > ResourceBundle itself. This field is needed to hold the bundle's > format for invoking the Control.needsReload() method. It is not > semantically correct to use the value from the LoadSession as done in > webrev.04. This has to be the value that the bundle was created with, > so it belongs to the bundle itself. In original code it was taken from > the cloned CacheKey that was attached to the bundle. > > All other changes from webrev.04 are limited to ResourceBundle.java > file and include some comments and nits that don't change the overall > logic. All ResourceBundle tests still pass. > > The diff from webrev.04 is the following: > > *** ResourceBundle.webrev.04.java 2016-08-01 15:33:49.408565452 > +0200 > --- ResourceBundle.java 2016-08-01 14:43:59.875401697 +0200 > *************** > *** 40,55 **** > > package java.util; > > - import jdk.internal.misc.JavaUtilResourceBundleAccess; > - import jdk.internal.misc.SharedSecrets; > - import jdk.internal.reflect.CallerSensitive; > - import jdk.internal.reflect.Reflection; > - import jdk.internal.util.concurrent.AbstractClassLoaderValue; > - import jdk.internal.util.concurrent.ClassLoaderValue; > - import sun.util.locale.BaseLocale; > - import sun.util.locale.LocaleObjectCache; > - import sun.util.locale.provider.ResourceBundleProviderSupport; > - > import java.io.IOException; > import java.io.InputStream; > import java.lang.ref.ReferenceQueue; > --- 40,45 ---- > *************** > *** 69,74 **** > --- 59,73 ---- > import java.util.spi.ResourceBundleControlProvider; > import java.util.spi.ResourceBundleProvider; > > + import jdk.internal.misc.JavaUtilResourceBundleAccess; > + import jdk.internal.misc.SharedSecrets; > + import jdk.internal.reflect.CallerSensitive; > + import jdk.internal.reflect.Reflection; > + import jdk.internal.util.concurrent.AbstractClassLoaderValue; > + import jdk.internal.util.concurrent.ClassLoaderValue; > + import sun.util.locale.BaseLocale; > + import sun.util.locale.LocaleObjectCache; > + import sun.util.locale.provider.ResourceBundleProviderSupport; > import static > sun.security.util.SecurityConstants.GET_CLASSLOADER_PERMISSION; > > > *************** > *** 346,354 **** > */ > public abstract class ResourceBundle { > > - /** initial size of the bundle cache */ > - private static final int INITIAL_CACHE_SIZE = 32; > - > static { > SharedSecrets.setJavaUtilResourceBundleAccess( > new JavaUtilResourceBundleAccess() { > --- 345,350 ---- > *************** > *** 386,392 **** > > > /** > ! * The cache of BundleReference(s) per class loader, bundle base > name and locale. > */ > private static final ClassLoaderValue cache > = new ClassLoaderValue<>(); > --- 382,389 ---- > > > /** > ! * The cache of BundleReference(s) per class loader, module, > bundle base name > ! * and locale. > */ > private static final ClassLoaderValue cache > = new ClassLoaderValue<>(); > *************** > *** 419,430 **** > * The parent bundle is searched by {@link #getObject getObject} > * when this bundle does not contain a particular resource. > */ > ! protected ResourceBundle parent = null; > > /** > * The locale for this bundle. > */ > ! private Locale locale = null; > > /** > * The base bundle name for this bundle. > --- 416,427 ---- > * The parent bundle is searched by {@link #getObject getObject} > * when this bundle does not contain a particular resource. > */ > ! protected ResourceBundle parent; > > /** > * The locale for this bundle. > */ > ! private Locale locale; > > /** > * The base bundle name for this bundle. > *************** > *** 432,437 **** > --- 429,440 ---- > private String name; > > /** > + * Bundle format which is necessary for calling > + * Control.needsReload(). > + */ > + private String format; > + > + /** > * The flag indicating this bundle has expired in the cache. > */ > private volatile boolean expired; > *************** > *** 622,629 **** > > /** > * A session object used during the {@link #getBundle} call. > ! * The loader may be null, but the base name, the locale and > ! * module must have a non-null value. > */ > private static class LoadSession { > // These four are the actual keys for lookup in cache. > --- 625,633 ---- > > /** > * A session object used during the {@link #getBundle} call. > ! * The loader may be null (in which case it is considered to be the > ! * bootstrap class loader), but the module, base name, and > locale must have > ! * a non-null value. > */ > private static class LoadSession { > // These four are the actual keys for lookup in cache. > *************** > *** 642,651 **** > return key().get(loader); > } > > - // bundle format which is necessary for calling > - // Control.needsReload(). > - private String format; > - > // Placeholder for an error report by a Throwable > private Throwable cause; > > --- 646,651 ---- > *************** > *** 699,712 **** > return callerHasProvider == Boolean.TRUE; > } > > - String getFormat() { > - return format; > - } > - > - void setFormat(String format) { > - this.format = format; > - } > - > private void setCause(Throwable cause) { > if (this.cause == null) { > this.cause = cause; > --- 699,704 ---- > *************** > *** 734,740 **** > } > } > return "LookupSession[" + name + ", lc=" + l + ", ldr=" > + getLoader() > ! + "(format=" + format + ")]"; > } > } > > --- 726,732 ---- > } > } > return "LookupSession[" + name + ", lc=" + l + ", ldr=" > + getLoader() > ! + "]"; > } > } > > *************** > *** 1666,1672 **** > bundle = loadBundleFromProviders(baseName, targetLocale, > providers, loadSession); > if (bundle != null) { > ! loadSession.setFormat(UNKNOWN_FORMAT); > } > } > // If none of providers returned a bundle and the caller has > no provider, > --- 1658,1664 ---- > bundle = loadBundleFromProviders(baseName, targetLocale, > providers, loadSession); > if (bundle != null) { > ! bundle.format = UNKNOWN_FORMAT; > } > } > // If none of providers returned a bundle and the caller has > no provider, > *************** > *** 1690,1696 **** > } > > if (bundle != null) { > ! loadSession.setFormat(format); > break; > } > } catch (Exception e) { > --- 1682,1688 ---- > } > > if (bundle != null) { > ! bundle.format = format; > break; > } > } catch (Exception e) { > *************** > *** 1764,1770 **** > Iterable providers, > LoadSession loadSession) > { > ! // assert cacheKey != null && providers != null; > return AccessController.doPrivileged( > new PrivilegedAction<>() { > public ResourceBundle run() { > --- 1756,1762 ---- > Iterable providers, > LoadSession loadSession) > { > ! // assert loadSession != null && providers != null; > return AccessController.doPrivileged( > new PrivilegedAction<>() { > public ResourceBundle run() { > *************** > *** 1819,1825 **** > if (bundle != null) { > // Set the format in the cache key so that it can be > // used when calling needsReload later. > ! loadSession.setFormat(format); > bundle.name = loadSession.getName(); > bundle.locale = targetLocale; > // Bundle provider might reuse instances. So we > should make > --- 1811,1817 ---- > if (bundle != null) { > // Set the format in the cache key so that it can be > // used when calling needsReload later. > ! bundle.format = format; > bundle.name = loadSession.getName(); > bundle.locale = targetLocale; > // Bundle provider might reuse instances. So we > should make > *************** > *** 1877,1883 **** > * Finds a bundle in the cache. Any expired bundles are marked as > * `expired' and removed from the cache upon return. > * > ! * @param loadSession the key to look up the cache > * @param control the Control to be used for the expiration control > * @return the cached bundle, or null if the bundle is not found > in the > * cache or its parent has expired. bundle.expire > is true > --- 1869,1875 ---- > * Finds a bundle in the cache. Any expired bundles are marked as > * `expired' and removed from the cache upon return. > * > ! * @param loadSession the load session used look up the cache > * @param control the Control to be used for the expiration control > * @return the cached bundle, or null if the bundle is not found > in the > * cache or its parent has expired. bundle.expire > is true > *************** > *** 1946,1954 **** > if (!bundle.expired && expirationTime >= 0 && > expirationTime <= > System.currentTimeMillis()) { > try { > ! bundle.expired = > control.needsReload(loadSession.getName(), > ! loadSession.getLocale(), > ! loadSession.getFormat(), > loadSession.getLoader(), > bundle, > bundle.loadTime); > --- 1938,1946 ---- > if (!bundle.expired && expirationTime >= 0 && > expirationTime <= > System.currentTimeMillis()) { > try { > ! bundle.expired = > control.needsReload(bundle.getBaseBundleName(), > ! bundle.getLocale(), > ! bundle.format, > loadSession.getLoader(), > bundle, > bundle.loadTime); > > > > In my opinion, the change of the semantics of > ResourceBundle.clearCache(ClassLoader) could be tolerated if the > invocation of that method was not a requirement for application > containers to be able to unload the app's class loader. With my > proposed change to caching it is not a requirement any more. > > Regards, Peter > > > On 07/25/2016 08:08 AM, Masayoshi Okutsu wrote: >> Hi Peter, >> >> The change (ResourceBundle part) looks very good to me. There's a >> simple workaround for the problem -- call >> ResourceBundle.clearCache(ClassLoader). So I don't know how serious >> the problem is, though. I still like this change. >> >> Yes, the comment in ReferenceTest should be removed. >> >> Thanks, >> Masayoshi >> >> On 7/22/2016 10:13 PM, Peter Levart wrote: >>> On 07/22/2016 10:46 AM, Peter Levart wrote: >>>> Hi Masayoshi, >>> >>> Here's a preview of work to migrate ResourceBundle caching to using >>> ClassLoaderValue utility: >>> >>> http://cr.openjdk.java.net/~plevart/jdk9-dev/ResourceBundle.cleanup/webrev.04/ >>> >>> >>> The changes are very straightforward. They preserve the general >>> structure of the logic. I renamed the CacheKey nested class to >>> LoadSession as it now only functions as a mutable object passed >>> around the methods while executing the getBundle() process. >>> LoadSession is now a factory for ClassLoaderValue cache key. I moved >>> the loadTime and expirationTime fields from LoadSession (old >>> CacheKey) to ResourceBundle. As each cached entry must maintain it's >>> own loadTime/expirationTime, I changed the NONEXISTENT_BUNDLE >>> constant into a private subclass of ResourceBundle. The back-link >>> from ResourceBundle to CacheKey is not needed any more. There is a >>> backlink from BundleReference to ClassLoaderValue key and the >>> associated ClassLoader to enable expunging. >>> >>> All 41 java/util/ResourceBundle tests pass with this change applied. >>> Including the ReferenceTest which I had to modify a little to remove >>> a dependency on ResourceBundle.cacheList field which is only used in >>> test to report the size of the Map. It is not possible to obtain the >>> size of the Map any more with this change applied, since the entries >>> are distributed to multiple Map(s) - one Map per ClassLoader >>> instance. The following comment in ReferenceTest could now be removed: >>> >>> * This test relies on the current behavior of the garbage collector >>> and is >>> * therefore no clear indicator of whether the fix for 4405807 works. >>> * If the test fails, it might indicate a regression, or it might >>> just mean >>> * that a less aggressive garbage collector is used. >>> >>> ...as the ClassLoader(s) unloading does not depend on eagerness of >>> SoftReference(s) clearing or any other activity any more. >>> >>> What do you think? >>> >>> Regards, Peter >>> >>>> >>>> Thinking of how the ResourceBundle caching is implemented, I think >>>> it has a serious flaw. The cache is currently the following: >>>> >>>> private static final ConcurrentMap >>>> cacheList >>>> >>>> ...where the CacheKey is an object which contains WeakReference(s) >>>> to the caller's ClassLoader and Module. This is OK. >>>> >>>> BundleReference, OTOH, is a SoftReference. The >>>> problem is ResourceBundle(s) can be arbitrary user subclasses, >>>> which means that they may have an implicit reference to the >>>> ClassLoader that appears in the CacheKey. The consequence is that >>>> such cache can prevent GC-ing of the ClassLoader for arbitrary >>>> amount of time (SoftReferences are cleared on memory pressure). >>>> >>>> Luckily there might be a solution. If the ResourceBundle subclasses >>>> are always resolvable from the ClassLoader that appears in the >>>> CacheKey, then there is a utility class that I created recently: >>>> java.lang.reflect.ClassLoaderValue. This a package-private class as >>>> it is currently used only in java.lang.reflect.Proxy for caching of >>>> dynamic Proxy classes, but could be made public and moved to some >>>> jdk.internal... package. >>>> >>>> Basing ResourceBundle caching on this utility class could also >>>> simplify the implementation as you wouldn't have to deal with >>>> WeakReference(s) to ClassLoader and Module objects. You could still >>>> have a BundleReference extending SoftReference to >>>> release the bundles on memory pressure but since such >>>> SoftReference(s) would be anchored in the particular ClassLoader >>>> instance that can resolve the ResourceBundle subclasses, it would >>>> not prevent such ClassLoader from being GCed immediately. >>>> >>>> I can prototype such caching if you like. >>>> >>>> Regards, Peter >>>> >>>> On 07/22/2016 06:07 AM, Masayoshi Okutsu wrote: >>>>> Hi Peter, >>>>> >>>>> Thank you for your suggestion. Actually CacheKey is used for >>>>> storing information required to load resource bundles during a >>>>> ResourceBundle.getBundle call. The current CacheKey usage may be >>>>> too tricky and cause some maintenance problems. I will file a >>>>> separate issue on that problem. I wanted to work on some clean up >>>>> of the CacheKey usage, but I haven't had a chance. >>>>> >>>>> Thanks, >>>>> Masayoshi >>>>> >>>>> >>>>> On 7/21/2016 10:13 PM, Peter Levart wrote: >>>>>> Hi Masayoshi, >>>>>> >>>>>> Previously the CacheKey::clone() method cleared a reference to >>>>>> 'providers' in the clone making the provides unreachable from the >>>>>> clone and making the clone unable to obtain providers. Now you >>>>>> also reset the 'providersChecked' flag which makes the clone be >>>>>> able to re-obtain the providers. This is dangerous as the clone >>>>>> is used as a key in the cache and is strongly reachable from the >>>>>> cache. A slight future modification of code could unintentionally >>>>>> produce a class loader leak. To prevent that, I would somehow >>>>>> mark the clone so that any attempt to invoke getProviders() on >>>>>> the clone would throw IllegalStateException. >>>>>> >>>>>> Regards, Peter >>>>>> >>>>>> On 07/21/2016 06:14 AM, Masayoshi Okutsu wrote: >>>>>>> Hi, >>>>>>> >>>>>>> Please review the fix for JDK-8161203. The fix is to lazily load >>>>>>> ResourceBundleProviders. It's not necessary to load providers >>>>>>> before cache look-up. >>>>>>> >>>>>>> Issue: >>>>>>> https://bugs.openjdk.java.net/browse/JDK-8161203 >>>>>>> >>>>>>> Webrev: >>>>>>> http://cr.openjdk.java.net/~okutsu/9/8161203/webrev.01 >>>>>>> >>>>>>> Thanks, >>>>>>> Masayoshi >>>>>>> >>>>>> >>>>> >>>> >>> >> > From yuka.kamiya at oracle.com Wed Aug 3 00:04:11 2016 From: yuka.kamiya at oracle.com (Yuka Kamiya) Date: Wed, 3 Aug 2016 09:04:11 +0900 Subject: Review Request for JDK-8035133: Locale matching: Weight q=0 isn't handled correctly. In-Reply-To: <21ceeb5f-1fd1-89d8-f6bc-f8fcf1df40a6@oracle.com> References: <21ceeb5f-1fd1-89d8-f6bc-f8fcf1df40a6@oracle.com> Message-ID: <8eb40169-705c-d5d5-9280-129ac2e0df99@oracle.com> Hi Nishit, The fix looks okay to me. Thanks, -- Yuka On 2016/08/02 14:53, Nishit Jain wrote: > Hi, > > Please review the fix for JDK-8035133 > > Bug: https://bugs.openjdk.java.net/browse/JDK-8035133 > Webrev: http://cr.openjdk.java.net/~nishjain/8035133/webrev.03/ > > Fix: Changed the filter and lookup mechanism to eliminate the matching > tags which are falling in the specified exclusion range i.e. the range > specified with quality weight 0 (q=0). The mechanism to handle q=0 was > not there in the previous implementation. > > Regards, > Nishit Jain > > From peter.levart at gmail.com Thu Aug 4 09:21:31 2016 From: peter.levart at gmail.com (Peter Levart) Date: Thu, 4 Aug 2016 11:21:31 +0200 Subject: ResourceBundleProvider(s) design Message-ID: Hi, I would like to ask about why java.util.spi.ResourceBundleProvider is designed they way it is. I'm questioning the design of the following part of specification: "The provider service type is determined by {@code basename+"Provider"}." Why is that necessary? It requires that provider service types are specialized per bundle base name. Each bundle base name requires a specific ResourceBundleProvider service subtype. This seems superfluous with the API point that ResourceBundleProvider declares: public interface ResourceBundleProvider { /** * Returns a {@code ResourceBundle} for the given bundle name and locale. * This method returns {@code null} if there is no {@code ResourceBundle} * found for the given parameters. * * * @param baseName * the base bundle name of the resource bundle, a fully * qualified class name * @param locale * the locale for which the resource bundle should be loaded * @return the ResourceBundle created for the given parameters, or null if no * {@code ResourceBundle} for the given parameters is found */ public ResourceBundle getBundle(String baseName, Locale locale); } .., the getBundle method takes a 'baseName' parameter. Why does it need such parameter when the service type already implies the bundle base name? What is the rationale behind such design? Who in this design (which module) is meant to define the service type for a particular bundle base name? The consuming module or the providing module? In case it is the consuming module, then the providing module will have an explicit dependency on the consuming module, which goes against the aim of service providers that provide services to multiple modules. If the providing module declares the service type, then the consuming module will have an explicit dependency on the providing module, which also defeats the purpose of service provider's implicit coupling. So the only thing left is to define the service types for each particular bundle base name in a special module that consumers and providers depend on. But this just goes against the aim of encapsulation. The bundle name should be a private contract between an unknown consumer and unknown provider - no other module(s) should be involved. A better design would be to not require that service type name be derived from bundle base name and have a constant service type regardless of bundle base name: java.util.spi.ResourceBundleProvider. So all providers would be polled for a particular bundle name and only the ones responsible for the particular name would respond with a non-null ResourceBundle instance. But this would present a problem in resolving of the transitive closure of dependent observable modules as it would pull-in all modules that provide bundles and not only those that provide bundles for required names. So without some additional resolution constraints this would present a problem. So I wonder whether the addition of ResourceBundleProvider service provider interface to ResourceBundle resolution process is a good idea at all. Now that resources are not encapsulated any more, " java.properties" format of bundles is resolvable among modules and "java.class" format of bundles too, when appropriate packages are exported. It feels that providing resource bundles via service provider infrastructure is too much fuss so no-one will use this mechanism if existing mechanism is more than adequate. Comments? Regards, Peter From peter.levart at gmail.com Thu Aug 4 10:26:05 2016 From: peter.levart at gmail.com (Peter Levart) Date: Thu, 4 Aug 2016 12:26:05 +0200 Subject: ResourceBundleProvider(s) design In-Reply-To: References: Message-ID: <5ad8e43c-bdc7-d6f2-6e9b-e6c4ed3bef70@gmail.com> On 08/04/2016 11:21 AM, Peter Levart wrote: > If the providing module declares the service type, then the consuming > module will have an explicit dependency on the providing module, which > also defeats the purpose of service provider's implicit coupling. I take this back. The service type is resolved at runtime by the ResourceBundle code using the consumer module's class loader and then ResourceBundleProvider interface is used to invoke its method. But I still think that the "baseName" parameter to this method is superfluous. I also see now that using resource bundle service providers is necessary if one wants to provide different modules for different languages covering a set of bundles - each language in its own module. Normally, for "java.class" format bundles, this would require per-language classes to be split among multiple modules and this is not possible as split packages are prohibited. With ResourceBundleProvider approach one can defined a ResourceBundleProvider service type in say "main language" module together with a default implementation and then various language implementations each in its own module with own package(s). For example: module consumer { uses my.BundleProvider; } // containing: package consumer; public class Main { public static void main(String ... args) { ResourceBundle.getBundle("my.Bundle", Locale.getDefault()); } } module my.bundle { exports my; provides my.BundleProvider with my.bundle.Bundle.Provider; } // containing: package my; public interface BundleProvider extends java.util.spi.ResourceBundleProvider {} module my.bundle.en { requires my.bundle; provides my.BundleProvider with my.bundle.en.Bundle.Provider; } module my.bundle.de { requires my.bundle; provides my.BundleProvider with my.bundle.de.Bundle.Provider; } etc... Regards, Peter From peter.levart at gmail.com Thu Aug 4 16:47:22 2016 From: peter.levart at gmail.com (Peter Levart) Date: Thu, 4 Aug 2016 18:47:22 +0200 Subject: RFR: 8161203: ResourceBundle.getBundle performance regression In-Reply-To: <0e19e8ab-570e-f9d6-4602-dee90adf213e@oracle.com> References: <7fc61181-7c3c-ea1c-d07a-90a2e712844c@oracle.com> <5991183a-8d2a-967d-74ec-c99e7d1636f3@oracle.com> <884a78a8-ebfb-a15d-a036-37b9fd377401@gmail.com> <2b8eb9f2-7b81-512b-6dde-0631d2c01c39@oracle.com> <4826d920-0ec2-5f97-5266-c53458ff779b@gmail.com> <0e19e8ab-570e-f9d6-4602-dee90adf213e@oracle.com> Message-ID: <1dc3c7f5-638f-339c-a935-178c6267d562@gmail.com> Hi Masayoshi, Just a thought. What if RB.clearCache(classLoader) was specified as equivalent to RB.clearCache(classLoader.getUnnamedModule()) ? I think that would be backwards compatible... Regards, Peter On 08/02/2016 05:30 PM, Masayoshi Okutsu wrote: > Hi Peter, > > Thanks for bringing up the semantics issue of clearCache. You are > right. There's some semantics change in clearCache(ClassLoader). Let > me look into it. > > The format field-related changes look good to me. > > Thanks, > Masayoshi > > On 8/1/2016 11:10 PM, Peter Levart wrote: >> Hi Masayosh, Alan, >> >> Thanks for looking at the change. >> >> I suppose application containers are already accustomed to invoke >> ResourceBundle.clearCache(ClassLoader) when undeploying an >> application so that the corresponding ClassLoader can get GCed right >> away. But there's a change in the semantics of this method that >> Jigsaw introduced... >> >> Before Jigsaw, this method was specified to: >> >> * Removes all resource bundles from the cache that have been loaded >> * using the given class loader. >> >> After Jigsaw, this method is specified to: >> >> * Removes all resource bundles from the cache that have been loaded >> * by the caller's module using the given class loader. >> >> >> Now suppose that the "caller's module" that loads the bundle is the >> application's module and the module that clears the cache is the >> container's module. The app's cache won't get cleared. I understand >> that the change in semantics was an attempt to "isolate" modules >> among themselves so that one module could not clear the cache of >> another module if they happen to map to the same class loader, but >> this also means that an application container can't easily clear the >> cache of the application it wishes to undeploy unless it uses the new >> ResourceBundle.clearCache(Module) method on each application's module >> before undeploying it. >> >> I also wonder if the change of the semantics of this method is >> backwards compatible. Suppose that some container is using this >> method to clear the cache of the application loaded by say >> "classloaderA" before undeploying it. It calls >> ResourceBundle.clearCache(classloaderA). Now suppose the container >> code is loaded by some other class loader (say "classloaderC") which >> is usually the case in today's containers. Both container and >> application classes are part of the unnamed modules of their >> corresponding class loaders. With the change in the semantics of this >> method introduced by jigsaw, the container will not clear the cache >> of the application any more since the container module is not the >> same as the application module (they are distinct unnamed modules). >> >> Anyway, I noticed an inconsistency in my webrev.04 immediately after >> posting it a week ago. I was off for a week then, so now that I'm >> back, here's the corrected webrev of my proposed change: >> >> http://cr.openjdk.java.net/~plevart/jdk9-dev/ResourceBundle.cleanup/webrev.05/ >> >> >> The only real change of logic compared to webrev.04 is that I moved >> the "format" field from the LoadSession (previous CacheKey) to >> ResourceBundle itself. This field is needed to hold the bundle's >> format for invoking the Control.needsReload() method. It is not >> semantically correct to use the value from the LoadSession as done in >> webrev.04. This has to be the value that the bundle was created with, >> so it belongs to the bundle itself. In original code it was taken >> from the cloned CacheKey that was attached to the bundle. >> >> All other changes from webrev.04 are limited to ResourceBundle.java >> file and include some comments and nits that don't change the overall >> logic. All ResourceBundle tests still pass. >> >> The diff from webrev.04 is the following: >> >> *** ResourceBundle.webrev.04.java 2016-08-01 15:33:49.408565452 >> +0200 >> --- ResourceBundle.java 2016-08-01 14:43:59.875401697 +0200 >> *************** >> *** 40,55 **** >> >> package java.util; >> >> - import jdk.internal.misc.JavaUtilResourceBundleAccess; >> - import jdk.internal.misc.SharedSecrets; >> - import jdk.internal.reflect.CallerSensitive; >> - import jdk.internal.reflect.Reflection; >> - import jdk.internal.util.concurrent.AbstractClassLoaderValue; >> - import jdk.internal.util.concurrent.ClassLoaderValue; >> - import sun.util.locale.BaseLocale; >> - import sun.util.locale.LocaleObjectCache; >> - import sun.util.locale.provider.ResourceBundleProviderSupport; >> - >> import java.io.IOException; >> import java.io.InputStream; >> import java.lang.ref.ReferenceQueue; >> --- 40,45 ---- >> *************** >> *** 69,74 **** >> --- 59,73 ---- >> import java.util.spi.ResourceBundleControlProvider; >> import java.util.spi.ResourceBundleProvider; >> >> + import jdk.internal.misc.JavaUtilResourceBundleAccess; >> + import jdk.internal.misc.SharedSecrets; >> + import jdk.internal.reflect.CallerSensitive; >> + import jdk.internal.reflect.Reflection; >> + import jdk.internal.util.concurrent.AbstractClassLoaderValue; >> + import jdk.internal.util.concurrent.ClassLoaderValue; >> + import sun.util.locale.BaseLocale; >> + import sun.util.locale.LocaleObjectCache; >> + import sun.util.locale.provider.ResourceBundleProviderSupport; >> import static >> sun.security.util.SecurityConstants.GET_CLASSLOADER_PERMISSION; >> >> >> *************** >> *** 346,354 **** >> */ >> public abstract class ResourceBundle { >> >> - /** initial size of the bundle cache */ >> - private static final int INITIAL_CACHE_SIZE = 32; >> - >> static { >> SharedSecrets.setJavaUtilResourceBundleAccess( >> new JavaUtilResourceBundleAccess() { >> --- 345,350 ---- >> *************** >> *** 386,392 **** >> >> >> /** >> ! * The cache of BundleReference(s) per class loader, bundle >> base name and locale. >> */ >> private static final ClassLoaderValue cache >> = new ClassLoaderValue<>(); >> --- 382,389 ---- >> >> >> /** >> ! * The cache of BundleReference(s) per class loader, module, >> bundle base name >> ! * and locale. >> */ >> private static final ClassLoaderValue cache >> = new ClassLoaderValue<>(); >> *************** >> *** 419,430 **** >> * The parent bundle is searched by {@link #getObject getObject} >> * when this bundle does not contain a particular resource. >> */ >> ! protected ResourceBundle parent = null; >> >> /** >> * The locale for this bundle. >> */ >> ! private Locale locale = null; >> >> /** >> * The base bundle name for this bundle. >> --- 416,427 ---- >> * The parent bundle is searched by {@link #getObject getObject} >> * when this bundle does not contain a particular resource. >> */ >> ! protected ResourceBundle parent; >> >> /** >> * The locale for this bundle. >> */ >> ! private Locale locale; >> >> /** >> * The base bundle name for this bundle. >> *************** >> *** 432,437 **** >> --- 429,440 ---- >> private String name; >> >> /** >> + * Bundle format which is necessary for calling >> + * Control.needsReload(). >> + */ >> + private String format; >> + >> + /** >> * The flag indicating this bundle has expired in the cache. >> */ >> private volatile boolean expired; >> *************** >> *** 622,629 **** >> >> /** >> * A session object used during the {@link #getBundle} call. >> ! * The loader may be null, but the base name, the locale and >> ! * module must have a non-null value. >> */ >> private static class LoadSession { >> // These four are the actual keys for lookup in cache. >> --- 625,633 ---- >> >> /** >> * A session object used during the {@link #getBundle} call. >> ! * The loader may be null (in which case it is considered to be >> the >> ! * bootstrap class loader), but the module, base name, and >> locale must have >> ! * a non-null value. >> */ >> private static class LoadSession { >> // These four are the actual keys for lookup in cache. >> *************** >> *** 642,651 **** >> return key().get(loader); >> } >> >> - // bundle format which is necessary for calling >> - // Control.needsReload(). >> - private String format; >> - >> // Placeholder for an error report by a Throwable >> private Throwable cause; >> >> --- 646,651 ---- >> *************** >> *** 699,712 **** >> return callerHasProvider == Boolean.TRUE; >> } >> >> - String getFormat() { >> - return format; >> - } >> - >> - void setFormat(String format) { >> - this.format = format; >> - } >> - >> private void setCause(Throwable cause) { >> if (this.cause == null) { >> this.cause = cause; >> --- 699,704 ---- >> *************** >> *** 734,740 **** >> } >> } >> return "LookupSession[" + name + ", lc=" + l + ", ldr=" >> + getLoader() >> ! + "(format=" + format + ")]"; >> } >> } >> >> --- 726,732 ---- >> } >> } >> return "LookupSession[" + name + ", lc=" + l + ", ldr=" >> + getLoader() >> ! + "]"; >> } >> } >> >> *************** >> *** 1666,1672 **** >> bundle = loadBundleFromProviders(baseName, targetLocale, >> providers, loadSession); >> if (bundle != null) { >> ! loadSession.setFormat(UNKNOWN_FORMAT); >> } >> } >> // If none of providers returned a bundle and the caller >> has no provider, >> --- 1658,1664 ---- >> bundle = loadBundleFromProviders(baseName, targetLocale, >> providers, loadSession); >> if (bundle != null) { >> ! bundle.format = UNKNOWN_FORMAT; >> } >> } >> // If none of providers returned a bundle and the caller >> has no provider, >> *************** >> *** 1690,1696 **** >> } >> >> if (bundle != null) { >> ! loadSession.setFormat(format); >> break; >> } >> } catch (Exception e) { >> --- 1682,1688 ---- >> } >> >> if (bundle != null) { >> ! bundle.format = format; >> break; >> } >> } catch (Exception e) { >> *************** >> *** 1764,1770 **** >> Iterable providers, >> LoadSession loadSession) >> { >> ! // assert cacheKey != null && providers != null; >> return AccessController.doPrivileged( >> new PrivilegedAction<>() { >> public ResourceBundle run() { >> --- 1756,1762 ---- >> Iterable providers, >> LoadSession loadSession) >> { >> ! // assert loadSession != null && providers != null; >> return AccessController.doPrivileged( >> new PrivilegedAction<>() { >> public ResourceBundle run() { >> *************** >> *** 1819,1825 **** >> if (bundle != null) { >> // Set the format in the cache key so that it can be >> // used when calling needsReload later. >> ! loadSession.setFormat(format); >> bundle.name = loadSession.getName(); >> bundle.locale = targetLocale; >> // Bundle provider might reuse instances. So we >> should make >> --- 1811,1817 ---- >> if (bundle != null) { >> // Set the format in the cache key so that it can be >> // used when calling needsReload later. >> ! bundle.format = format; >> bundle.name = loadSession.getName(); >> bundle.locale = targetLocale; >> // Bundle provider might reuse instances. So we >> should make >> *************** >> *** 1877,1883 **** >> * Finds a bundle in the cache. Any expired bundles are marked as >> * `expired' and removed from the cache upon return. >> * >> ! * @param loadSession the key to look up the cache >> * @param control the Control to be used for the expiration >> control >> * @return the cached bundle, or null if the bundle is not >> found in the >> * cache or its parent has expired. bundle.expire >> is true >> --- 1869,1875 ---- >> * Finds a bundle in the cache. Any expired bundles are marked as >> * `expired' and removed from the cache upon return. >> * >> ! * @param loadSession the load session used look up the cache >> * @param control the Control to be used for the expiration >> control >> * @return the cached bundle, or null if the bundle is not >> found in the >> * cache or its parent has expired. bundle.expire >> is true >> *************** >> *** 1946,1954 **** >> if (!bundle.expired && expirationTime >= 0 && >> expirationTime <= >> System.currentTimeMillis()) { >> try { >> ! bundle.expired = >> control.needsReload(loadSession.getName(), >> ! loadSession.getLocale(), >> ! loadSession.getFormat(), >> loadSession.getLoader(), >> bundle, >> bundle.loadTime); >> --- 1938,1946 ---- >> if (!bundle.expired && expirationTime >= 0 && >> expirationTime <= >> System.currentTimeMillis()) { >> try { >> ! bundle.expired = >> control.needsReload(bundle.getBaseBundleName(), >> ! bundle.getLocale(), >> ! bundle.format, >> loadSession.getLoader(), >> bundle, >> bundle.loadTime); >> >> >> >> In my opinion, the change of the semantics of >> ResourceBundle.clearCache(ClassLoader) could be tolerated if the >> invocation of that method was not a requirement for application >> containers to be able to unload the app's class loader. With my >> proposed change to caching it is not a requirement any more. >> >> Regards, Peter >> >> >> On 07/25/2016 08:08 AM, Masayoshi Okutsu wrote: >>> Hi Peter, >>> >>> The change (ResourceBundle part) looks very good to me. There's a >>> simple workaround for the problem -- call >>> ResourceBundle.clearCache(ClassLoader). So I don't know how serious >>> the problem is, though. I still like this change. >>> >>> Yes, the comment in ReferenceTest should be removed. >>> >>> Thanks, >>> Masayoshi >>> >>> On 7/22/2016 10:13 PM, Peter Levart wrote: >>>> On 07/22/2016 10:46 AM, Peter Levart wrote: >>>>> Hi Masayoshi, >>>> >>>> Here's a preview of work to migrate ResourceBundle caching to using >>>> ClassLoaderValue utility: >>>> >>>> http://cr.openjdk.java.net/~plevart/jdk9-dev/ResourceBundle.cleanup/webrev.04/ >>>> >>>> >>>> The changes are very straightforward. They preserve the general >>>> structure of the logic. I renamed the CacheKey nested class to >>>> LoadSession as it now only functions as a mutable object passed >>>> around the methods while executing the getBundle() process. >>>> LoadSession is now a factory for ClassLoaderValue cache key. I >>>> moved the loadTime and expirationTime fields from LoadSession (old >>>> CacheKey) to ResourceBundle. As each cached entry must maintain >>>> it's own loadTime/expirationTime, I changed the NONEXISTENT_BUNDLE >>>> constant into a private subclass of ResourceBundle. The back-link >>>> from ResourceBundle to CacheKey is not needed any more. There is a >>>> backlink from BundleReference to ClassLoaderValue key and the >>>> associated ClassLoader to enable expunging. >>>> >>>> All 41 java/util/ResourceBundle tests pass with this change >>>> applied. Including the ReferenceTest which I had to modify a little >>>> to remove a dependency on ResourceBundle.cacheList field which is >>>> only used in test to report the size of the Map. It is not possible >>>> to obtain the size of the Map any more with this change applied, >>>> since the entries are distributed to multiple Map(s) - one Map per >>>> ClassLoader instance. The following comment in ReferenceTest could >>>> now be removed: >>>> >>>> * This test relies on the current behavior of the garbage >>>> collector and is >>>> * therefore no clear indicator of whether the fix for 4405807 works. >>>> * If the test fails, it might indicate a regression, or it might >>>> just mean >>>> * that a less aggressive garbage collector is used. >>>> >>>> ...as the ClassLoader(s) unloading does not depend on eagerness of >>>> SoftReference(s) clearing or any other activity any more. >>>> >>>> What do you think? >>>> >>>> Regards, Peter >>>> >>>>> >>>>> Thinking of how the ResourceBundle caching is implemented, I think >>>>> it has a serious flaw. The cache is currently the following: >>>>> >>>>> private static final ConcurrentMap >>>>> cacheList >>>>> >>>>> ...where the CacheKey is an object which contains WeakReference(s) >>>>> to the caller's ClassLoader and Module. This is OK. >>>>> >>>>> BundleReference, OTOH, is a SoftReference. The >>>>> problem is ResourceBundle(s) can be arbitrary user subclasses, >>>>> which means that they may have an implicit reference to the >>>>> ClassLoader that appears in the CacheKey. The consequence is that >>>>> such cache can prevent GC-ing of the ClassLoader for arbitrary >>>>> amount of time (SoftReferences are cleared on memory pressure). >>>>> >>>>> Luckily there might be a solution. If the ResourceBundle >>>>> subclasses are always resolvable from the ClassLoader that appears >>>>> in the CacheKey, then there is a utility class that I created >>>>> recently: java.lang.reflect.ClassLoaderValue. This a >>>>> package-private class as it is currently used only in >>>>> java.lang.reflect.Proxy for caching of dynamic Proxy classes, but >>>>> could be made public and moved to some jdk.internal... package. >>>>> >>>>> Basing ResourceBundle caching on this utility class could also >>>>> simplify the implementation as you wouldn't have to deal with >>>>> WeakReference(s) to ClassLoader and Module objects. You could >>>>> still have a BundleReference extending >>>>> SoftReference to release the bundles on memory >>>>> pressure but since such SoftReference(s) would be anchored in the >>>>> particular ClassLoader instance that can resolve the >>>>> ResourceBundle subclasses, it would not prevent such ClassLoader >>>>> from being GCed immediately. >>>>> >>>>> I can prototype such caching if you like. >>>>> >>>>> Regards, Peter >>>>> >>>>> On 07/22/2016 06:07 AM, Masayoshi Okutsu wrote: >>>>>> Hi Peter, >>>>>> >>>>>> Thank you for your suggestion. Actually CacheKey is used for >>>>>> storing information required to load resource bundles during a >>>>>> ResourceBundle.getBundle call. The current CacheKey usage may be >>>>>> too tricky and cause some maintenance problems. I will file a >>>>>> separate issue on that problem. I wanted to work on some clean up >>>>>> of the CacheKey usage, but I haven't had a chance. >>>>>> >>>>>> Thanks, >>>>>> Masayoshi >>>>>> >>>>>> >>>>>> On 7/21/2016 10:13 PM, Peter Levart wrote: >>>>>>> Hi Masayoshi, >>>>>>> >>>>>>> Previously the CacheKey::clone() method cleared a reference to >>>>>>> 'providers' in the clone making the provides unreachable from >>>>>>> the clone and making the clone unable to obtain providers. Now >>>>>>> you also reset the 'providersChecked' flag which makes the clone >>>>>>> be able to re-obtain the providers. This is dangerous as the >>>>>>> clone is used as a key in the cache and is strongly reachable >>>>>>> from the cache. A slight future modification of code could >>>>>>> unintentionally produce a class loader leak. To prevent that, I >>>>>>> would somehow mark the clone so that any attempt to invoke >>>>>>> getProviders() on the clone would throw IllegalStateException. >>>>>>> >>>>>>> Regards, Peter >>>>>>> >>>>>>> On 07/21/2016 06:14 AM, Masayoshi Okutsu wrote: >>>>>>>> Hi, >>>>>>>> >>>>>>>> Please review the fix for JDK-8161203. The fix is to lazily >>>>>>>> load ResourceBundleProviders. It's not necessary to load >>>>>>>> providers before cache look-up. >>>>>>>> >>>>>>>> Issue: >>>>>>>> https://bugs.openjdk.java.net/browse/JDK-8161203 >>>>>>>> >>>>>>>> Webrev: >>>>>>>> http://cr.openjdk.java.net/~okutsu/9/8161203/webrev.01 >>>>>>>> >>>>>>>> Thanks, >>>>>>>> Masayoshi >>>>>>>> >>>>>>> >>>>>> >>>>> >>>> >>> >> > From mandy.chung at oracle.com Mon Aug 8 19:55:53 2016 From: mandy.chung at oracle.com (Mandy Chung) Date: Mon, 8 Aug 2016 12:55:53 -0700 Subject: ResourceBundleProvider(s) design In-Reply-To: <5ad8e43c-bdc7-d6f2-6e9b-e6c4ed3bef70@gmail.com> References: <5ad8e43c-bdc7-d6f2-6e9b-e6c4ed3bef70@gmail.com> Message-ID: Hi Peter, Sorry for the delay in reply. Still catching up on mails from vacation. > On Aug 4, 2016, at 3:26 AM, Peter Levart wrote: > > > On 08/04/2016 11:21 AM, Peter Levart wrote: >> If the providing module declares the service type, then the consuming module will have an explicit dependency on the providing module, which also defeats the purpose of service provider's implicit coupling. > > I take this back. The service type is resolved at runtime by the ResourceBundle code using the consumer module's class loader and then ResourceBundleProvider interface is used to invoke its method. Exactly. > But I still think that the "baseName" parameter to this method is superfluous. > A resource bundle provider may provide different bundles, i.e. different base names and so it can implement multiple service interfaces. > I also see now that using resource bundle service providers is necessary if one wants to provide different modules for different languages covering a set of bundles - each language in its own module. Normally, for "java.class" format bundles, this would require per-language classes to be split among multiple modules and this is not possible as split packages are prohibited. With ResourceBundleProvider approach one can defined a ResourceBundleProvider service type in say "main language" module together with a default implementation and then various language implementations each in its own module with own package(s). For example: > > module consumer { > uses my.BundleProvider; > } > // containing: > package consumer; > public class Main { > public static void main(String ... args) { > ResourceBundle.getBundle("my.Bundle", Locale.getDefault()); > } > } > > > module my.bundle { > exports my; > provides my.BundleProvider with my.bundle.Bundle.Provider; > } > // containing: > package my; > public interface BundleProvider extends java.util.spi.ResourceBundleProvider {} > > > module my.bundle.en { > requires my.bundle; > provides my.BundleProvider with my.bundle.en.Bundle.Provider; > } > > > module my.bundle.de { > requires my.bundle; > provides my.BundleProvider with my.bundle.de.Bundle.Provider; > } > > > etc? jdk/test/java/util/ResourceBundles/modules have a few examples. Perhaps we should improve the javadoc of ResourceBundleProvider and code example to make this clearer? Mandy From rachna.goel at oracle.com Tue Aug 9 10:51:05 2016 From: rachna.goel at oracle.com (Rachna Goel) Date: Tue, 9 Aug 2016 16:21:05 +0530 Subject: Review Request:JDK-8163350-LocaleProviderAdapter Preference list retrieved is wrong, when -Djava.locale.providers=COMPAT Message-ID: Hi, Please review fix for JDK-8163350. Bug: https://bugs.openjdk.java.net/browse/JDK-8163350 Webrev: http://cr.openjdk.java.net/~rgoel/jdk-8163350/webrev.02/ Fix: If user specifies either CLDR or COMPAT via System Property, FALLBACK should not be implicitly included. It is meant to be included when no ResourceBundleBased Adapters are available. Thanks, Rachna From naoto.sato at oracle.com Tue Aug 9 16:09:33 2016 From: naoto.sato at oracle.com (Naoto Sato) Date: Tue, 9 Aug 2016 09:09:33 -0700 Subject: Review Request:JDK-8163350-LocaleProviderAdapter Preference list retrieved is wrong, when -Djava.locale.providers=COMPAT In-Reply-To: References: Message-ID: <2ef585b1-7679-1d25-4827-7e0ef5b15046@oracle.com> Hi Rachna, I should've caught it at the internal review, but here are some cosmetic comments to the test case. - I'd prefer a blank line between import statements and the main method. - The argument to main() should be (String[] args) - Indentation is incorrect at line 39 - Needs parens for the if statement at line 41. Naoto On 8/9/16 3:51 AM, Rachna Goel wrote: > Hi, > > Please review fix for JDK-8163350. > > Bug: https://bugs.openjdk.java.net/browse/JDK-8163350 > > Webrev: http://cr.openjdk.java.net/~rgoel/jdk-8163350/webrev.02/ > > Fix: If user specifies either CLDR or COMPAT via System Property, > FALLBACK should not be implicitly included. > > It is meant to be included when no ResourceBundleBased Adapters are > available. > > Thanks, > > Rachna > From rachna.goel at oracle.com Tue Aug 9 17:31:32 2016 From: rachna.goel at oracle.com (Rachna Goel) Date: Tue, 9 Aug 2016 23:01:32 +0530 Subject: Review Request:JDK-8163350-LocaleProviderAdapter Preference list retrieved is wrong, when -Djava.locale.providers=COMPAT In-Reply-To: <2ef585b1-7679-1d25-4827-7e0ef5b15046@oracle.com> References: <2ef585b1-7679-1d25-4827-7e0ef5b15046@oracle.com> Message-ID: Hi Naoto, Thanks for the review. Please have a look at updated patch: http://cr.openjdk.java.net/~rgoel/jdk-8163350/webrev.03/ Thanks, Rachna On 8/9/16 9:39 PM, Naoto Sato wrote: > Hi Rachna, > > I should've caught it at the internal review, but here are some > cosmetic comments to the test case. > > - I'd prefer a blank line between import statements and the main method. > - The argument to main() should be (String[] args) > - Indentation is incorrect at line 39 > - Needs parens for the if statement at line 41. > > Naoto > > On 8/9/16 3:51 AM, Rachna Goel wrote: >> Hi, >> >> Please review fix for JDK-8163350. >> >> Bug: https://bugs.openjdk.java.net/browse/JDK-8163350 >> >> Webrev: http://cr.openjdk.java.net/~rgoel/jdk-8163350/webrev.02/ >> >> Fix: If user specifies either CLDR or COMPAT via System Property, >> FALLBACK should not be implicitly included. >> >> It is meant to be included when no ResourceBundleBased Adapters are >> available. >> >> Thanks, >> >> Rachna >> From naoto.sato at oracle.com Tue Aug 9 17:47:42 2016 From: naoto.sato at oracle.com (Naoto Sato) Date: Tue, 9 Aug 2016 10:47:42 -0700 Subject: Review Request:JDK-8163350-LocaleProviderAdapter Preference list retrieved is wrong, when -Djava.locale.providers=COMPAT In-Reply-To: References: <2ef585b1-7679-1d25-4827-7e0ef5b15046@oracle.com> Message-ID: <798bf26e-e380-914d-48b9-ca1817df2157@oracle.com> +1 Naoto On 8/9/16 10:31 AM, Rachna Goel wrote: > Hi Naoto, > > Thanks for the review. > > Please have a look at updated patch: > > http://cr.openjdk.java.net/~rgoel/jdk-8163350/webrev.03/ > > Thanks, > > Rachna > > > > On 8/9/16 9:39 PM, Naoto Sato wrote: >> Hi Rachna, >> >> I should've caught it at the internal review, but here are some >> cosmetic comments to the test case. >> >> - I'd prefer a blank line between import statements and the main method. >> - The argument to main() should be (String[] args) >> - Indentation is incorrect at line 39 >> - Needs parens for the if statement at line 41. >> >> Naoto >> >> On 8/9/16 3:51 AM, Rachna Goel wrote: >>> Hi, >>> >>> Please review fix for JDK-8163350. >>> >>> Bug: https://bugs.openjdk.java.net/browse/JDK-8163350 >>> >>> Webrev: http://cr.openjdk.java.net/~rgoel/jdk-8163350/webrev.02/ >>> >>> Fix: If user specifies either CLDR or COMPAT via System Property, >>> FALLBACK should not be implicitly included. >>> >>> It is meant to be included when no ResourceBundleBased Adapters are >>> available. >>> >>> Thanks, >>> >>> Rachna >>> > From nishit.jain at oracle.com Tue Aug 16 05:26:20 2016 From: nishit.jain at oracle.com (Nishit Jain) Date: Tue, 16 Aug 2016 10:56:20 +0530 Subject: Review Request for JDK-8129555: DateFormatSymbols: month-related methods must refer to Calendar constants Message-ID: Hi, Please review the fix for JDK-8129555 Bug: https://bugs.openjdk.java.net/browse/JDK-8129555 Webrev: http://cr.openjdk.java.net/~nishjain/8129555/webrev.02/ Fix: Added references to the Calendar constants in the api spec of the month related methods. Also, made some minor format changes in the spec of weekdays methods. Regards, Nishit Jain From masayoshi.okutsu at oracle.com Tue Aug 16 05:38:29 2016 From: masayoshi.okutsu at oracle.com (Masayoshi Okutsu) Date: Tue, 16 Aug 2016 14:38:29 +0900 Subject: Review Request for JDK-8129555: DateFormatSymbols: month-related methods must refer to Calendar constants In-Reply-To: References: Message-ID: Looks good to me. Masayoshi On 8/16/2016 2:26 PM, Nishit Jain wrote: > Hi, > > Please review the fix for JDK-8129555 > > Bug: https://bugs.openjdk.java.net/browse/JDK-8129555 > Webrev: http://cr.openjdk.java.net/~nishjain/8129555/webrev.02/ > > Fix: Added references to the Calendar constants in the api spec of the > month related methods. Also, made some minor format changes in the > spec of weekdays methods. > > Regards, > Nishit Jain From yuka.kamiya at oracle.com Tue Aug 16 06:20:17 2016 From: yuka.kamiya at oracle.com (Yuka Kamiya) Date: Tue, 16 Aug 2016 15:20:17 +0900 Subject: Review Request for JDK-8129555: DateFormatSymbols: month-related methods must refer to Calendar constants In-Reply-To: References: Message-ID: <0fac438e-b846-2a9b-135e-17260eb0c069@oracle.com> +1 On 2016/08/16 14:38, Masayoshi Okutsu wrote: > Looks good to me. > > Masayoshi > > > On 8/16/2016 2:26 PM, Nishit Jain wrote: >> Hi, >> >> Please review the fix for JDK-8129555 >> >> Bug: https://bugs.openjdk.java.net/browse/JDK-8129555 >> Webrev: http://cr.openjdk.java.net/~nishjain/8129555/webrev.02/ >> >> Fix: Added references to the Calendar constants in the api spec of >> the month related methods. Also, made some minor format changes in >> the spec of weekdays methods. >> >> Regards, >> Nishit Jain > From masayoshi.okutsu at oracle.com Tue Aug 16 07:46:29 2016 From: masayoshi.okutsu at oracle.com (Masayoshi Okutsu) Date: Tue, 16 Aug 2016 16:46:29 +0900 Subject: Review Request:JDK-8163350-LocaleProviderAdapter Preference list retrieved is wrong, when -Djava.locale.providers=COMPAT In-Reply-To: References: <2ef585b1-7679-1d25-4827-7e0ef5b15046@oracle.com> Message-ID: Hi Rachna, The fix looks good to me. But the test should be changed. - It's unnecessary to statically import sun.util.locale.provider.LocaleProviderAdapter.Type. - Variable name PreferenceList should be preferenceList. - No need to initialize preferenceList with an ArrayList. Thanks, Masayoshi On 8/10/2016 2:31 AM, Rachna Goel wrote: > Hi Naoto, > > Thanks for the review. > > Please have a look at updated patch: > > http://cr.openjdk.java.net/~rgoel/jdk-8163350/webrev.03/ > > Thanks, > > Rachna > > > > On 8/9/16 9:39 PM, Naoto Sato wrote: >> Hi Rachna, >> >> I should've caught it at the internal review, but here are some >> cosmetic comments to the test case. >> >> - I'd prefer a blank line between import statements and the main method. >> - The argument to main() should be (String[] args) >> - Indentation is incorrect at line 39 >> - Needs parens for the if statement at line 41. >> >> Naoto >> >> On 8/9/16 3:51 AM, Rachna Goel wrote: >>> Hi, >>> >>> Please review fix for JDK-8163350. >>> >>> Bug: https://bugs.openjdk.java.net/browse/JDK-8163350 >>> >>> Webrev: http://cr.openjdk.java.net/~rgoel/jdk-8163350/webrev.02/ >>> >>> Fix: If user specifies either CLDR or COMPAT via System Property, >>> FALLBACK should not be implicitly included. >>> >>> It is meant to be included when no ResourceBundleBased Adapters are >>> available. >>> >>> Thanks, >>> >>> Rachna >>> > From naoto.sato at oracle.com Wed Aug 17 16:28:28 2016 From: naoto.sato at oracle.com (Naoto Sato) Date: Wed, 17 Aug 2016 09:28:28 -0700 Subject: Review Request for JDK-8129555: DateFormatSymbols: month-related methods must refer to Calendar constants In-Reply-To: <0fac438e-b846-2a9b-135e-17260eb0c069@oracle.com> References: <0fac438e-b846-2a9b-135e-17260eb0c069@oracle.com> Message-ID: <478526cd-f0f5-ef30-63c6-47eca0382159@oracle.com> +1 as well. Naoto On 8/15/16 11:20 PM, Yuka Kamiya wrote: > +1 > > On 2016/08/16 14:38, Masayoshi Okutsu wrote: >> Looks good to me. >> >> Masayoshi >> >> >> On 8/16/2016 2:26 PM, Nishit Jain wrote: >>> Hi, >>> >>> Please review the fix for JDK-8129555 >>> >>> Bug: https://bugs.openjdk.java.net/browse/JDK-8129555 >>> Webrev: http://cr.openjdk.java.net/~nishjain/8129555/webrev.02/ >>> >>> Fix: Added references to the Calendar constants in the api spec of >>> the month related methods. Also, made some minor format changes in >>> the spec of weekdays methods. >>> >>> Regards, >>> Nishit Jain >> > From yuka.kamiya at oracle.com Mon Aug 22 01:31:22 2016 From: yuka.kamiya at oracle.com (Yuka Kamiya) Date: Mon, 22 Aug 2016 10:31:22 +0900 Subject: RFR: JDK-7094818, JDK-8132861 and JDK-8134733 Message-ID: <822479cc-2ba9-fa54-563a-9d7296a6ca5d@oracle.com> Hello, http://cr.openjdk.java.net/~peytoia/7094818.8132861.8134733/webrev.00/ Please review the fix for the following bugs: https://bugs.openjdk.java.net/browse/JDK-7094818 https://bugs.openjdk.java.net/browse/JDK-8132861 https://bugs.openjdk.java.net/browse/JDK-8134733 Thanks, -- Yuka From rachna.goel at oracle.com Mon Aug 22 04:10:49 2016 From: rachna.goel at oracle.com (Rachna Goel) Date: Mon, 22 Aug 2016 09:40:49 +0530 Subject: Review Request:JDK-8163350-LocaleProviderAdapter Preference list retrieved is wrong, when -Djava.locale.providers=COMPAT In-Reply-To: References: <2ef585b1-7679-1d25-4827-7e0ef5b15046@oracle.com> Message-ID: Hi Masayoshi, Thanks for the review. please have a look at updated webrev http://cr.openjdk.java.net/~rgoel/jdk-8163350/webrev.04/ Thanks, Rachna On 8/16/16 1:16 PM, Masayoshi Okutsu wrote: > Hi Rachna, > > The fix looks good to me. But the test should be changed. > > - It's unnecessary to statically import > sun.util.locale.provider.LocaleProviderAdapter.Type. > - Variable name PreferenceList should be preferenceList. > - No need to initialize preferenceList with an ArrayList. > > Thanks, > Masayoshi > > On 8/10/2016 2:31 AM, Rachna Goel wrote: >> Hi Naoto, >> >> Thanks for the review. >> >> Please have a look at updated patch: >> >> http://cr.openjdk.java.net/~rgoel/jdk-8163350/webrev.03/ >> >> Thanks, >> >> Rachna >> >> >> >> On 8/9/16 9:39 PM, Naoto Sato wrote: >>> Hi Rachna, >>> >>> I should've caught it at the internal review, but here are some >>> cosmetic comments to the test case. >>> >>> - I'd prefer a blank line between import statements and the main >>> method. >>> - The argument to main() should be (String[] args) >>> - Indentation is incorrect at line 39 >>> - Needs parens for the if statement at line 41. >>> >>> Naoto >>> >>> On 8/9/16 3:51 AM, Rachna Goel wrote: >>>> Hi, >>>> >>>> Please review fix for JDK-8163350. >>>> >>>> Bug: https://bugs.openjdk.java.net/browse/JDK-8163350 >>>> >>>> Webrev: http://cr.openjdk.java.net/~rgoel/jdk-8163350/webrev.02/ >>>> >>>> Fix: If user specifies either CLDR or COMPAT via System Property, >>>> FALLBACK should not be implicitly included. >>>> >>>> It is meant to be included when no ResourceBundleBased Adapters are >>>> available. >>>> >>>> Thanks, >>>> >>>> Rachna >>>> >> > From rachna.goel at oracle.com Mon Aug 22 04:26:49 2016 From: rachna.goel at oracle.com (Rachna Goel) Date: Mon, 22 Aug 2016 09:56:49 +0530 Subject: RFR: JDK-8163362-Reconsider reflection usage in java.awt.font.JavaAWTFontAccessImpl class Message-ID: <29344508-a30c-1920-d972-d25262d5311d@oracle.com> Hi, Please review fix for JDK-8163362. https://bugs.openjdk.java.net/browse/JDK-8163362 Webrev: http://cr.openjdk.java.net/~rgoel/JDK-8163362/webrev.01/ This is a cleanup fix in which Reflection usage in JavaAWTFontAccessImpl class was removed. Thanks, Rachna From rachna.goel at oracle.com Mon Aug 22 04:51:17 2016 From: rachna.goel at oracle.com (Rachna Goel) Date: Mon, 22 Aug 2016 10:21:17 +0530 Subject: RFR: JDK-8135055.java.util.Date.after(java.sql.Timestamp ) does not return correct results Message-ID: <13862b98-7c07-ce8f-931f-04876d9dec05@oracle.com> Hi, Please review fix for JDK-8135055. Bug: https://bugs.openjdk.java.net/browse/JDK-8135055 Webrev: http://cr.openjdk.java.net/~rgoel/JDK-8135055/webrev.02/ Fix is to return getTime() if argument to getMillisOf() is an instance of java.sql.TimeStamp. Thanks, Rachna From masayoshi.okutsu at oracle.com Mon Aug 22 05:20:13 2016 From: masayoshi.okutsu at oracle.com (Masayoshi Okutsu) Date: Mon, 22 Aug 2016 14:20:13 +0900 Subject: RFR: JDK-7094818, JDK-8132861 and JDK-8134733 In-Reply-To: <822479cc-2ba9-fa54-563a-9d7296a6ca5d@oracle.com> References: <822479cc-2ba9-fa54-563a-9d7296a6ca5d@oracle.com> Message-ID: <30e6ae7b-8d93-30ca-b036-366edad900b4@oracle.com> Looks good to me. Masayoshi On 8/22/2016 10:31 AM, Yuka Kamiya wrote: > Hello, > > http://cr.openjdk.java.net/~peytoia/7094818.8132861.8134733/webrev.00/ > > Please review the fix for the following bugs: > > https://bugs.openjdk.java.net/browse/JDK-7094818 > https://bugs.openjdk.java.net/browse/JDK-8132861 > https://bugs.openjdk.java.net/browse/JDK-8134733 > > Thanks, > -- > Yuka From masayoshi.okutsu at oracle.com Mon Aug 22 05:47:29 2016 From: masayoshi.okutsu at oracle.com (Masayoshi Okutsu) Date: Mon, 22 Aug 2016 14:47:29 +0900 Subject: Review Request:JDK-8163350-LocaleProviderAdapter Preference list retrieved is wrong, when -Djava.locale.providers=COMPAT In-Reply-To: References: <2ef585b1-7679-1d25-4827-7e0ef5b15046@oracle.com> Message-ID: <32753146-67d2-7aea-3e6f-7edc01cbbe9d@oracle.com> Looks good to me. Masayoshi On 8/22/2016 1:10 PM, Rachna Goel wrote: > Hi Masayoshi, > > Thanks for the review. > > please have a look at updated webrev > > http://cr.openjdk.java.net/~rgoel/jdk-8163350/webrev.04/ > > Thanks, > > Rachna > > > On 8/16/16 1:16 PM, Masayoshi Okutsu wrote: >> Hi Rachna, >> >> The fix looks good to me. But the test should be changed. >> >> - It's unnecessary to statically import >> sun.util.locale.provider.LocaleProviderAdapter.Type. >> - Variable name PreferenceList should be preferenceList. >> - No need to initialize preferenceList with an ArrayList. >> >> Thanks, >> Masayoshi >> >> On 8/10/2016 2:31 AM, Rachna Goel wrote: >>> Hi Naoto, >>> >>> Thanks for the review. >>> >>> Please have a look at updated patch: >>> >>> http://cr.openjdk.java.net/~rgoel/jdk-8163350/webrev.03/ >>> >>> Thanks, >>> >>> Rachna >>> >>> >>> >>> On 8/9/16 9:39 PM, Naoto Sato wrote: >>>> Hi Rachna, >>>> >>>> I should've caught it at the internal review, but here are some >>>> cosmetic comments to the test case. >>>> >>>> - I'd prefer a blank line between import statements and the main >>>> method. >>>> - The argument to main() should be (String[] args) >>>> - Indentation is incorrect at line 39 >>>> - Needs parens for the if statement at line 41. >>>> >>>> Naoto >>>> >>>> On 8/9/16 3:51 AM, Rachna Goel wrote: >>>>> Hi, >>>>> >>>>> Please review fix for JDK-8163350. >>>>> >>>>> Bug: https://bugs.openjdk.java.net/browse/JDK-8163350 >>>>> >>>>> Webrev: http://cr.openjdk.java.net/~rgoel/jdk-8163350/webrev.02/ >>>>> >>>>> Fix: If user specifies either CLDR or COMPAT via System Property, >>>>> FALLBACK should not be implicitly included. >>>>> >>>>> It is meant to be included when no ResourceBundleBased Adapters are >>>>> available. >>>>> >>>>> Thanks, >>>>> >>>>> Rachna >>>>> >>> >> > From masayoshi.okutsu at oracle.com Mon Aug 22 05:58:16 2016 From: masayoshi.okutsu at oracle.com (Masayoshi Okutsu) Date: Mon, 22 Aug 2016 14:58:16 +0900 Subject: RFR: JDK-8135055.java.util.Date.after(java.sql.Timestamp ) does not return correct results In-Reply-To: <13862b98-7c07-ce8f-931f-04876d9dec05@oracle.com> References: <13862b98-7c07-ce8f-931f-04876d9dec05@oracle.com> Message-ID: <32fe59e7-ab72-a5e9-4665-c9f8ad7e992b@oracle.com> Looks good to me. Masayoshi On 8/22/2016 1:51 PM, Rachna Goel wrote: > Hi, > > Please review fix for JDK-8135055. > > Bug: https://bugs.openjdk.java.net/browse/JDK-8135055 > > Webrev: http://cr.openjdk.java.net/~rgoel/JDK-8135055/webrev.02/ > > Fix is to return getTime() if argument to getMillisOf() is an > instance of java.sql.TimeStamp. > > Thanks, > > Rachna > From masayoshi.okutsu at oracle.com Mon Aug 22 06:11:32 2016 From: masayoshi.okutsu at oracle.com (Masayoshi Okutsu) Date: Mon, 22 Aug 2016 15:11:32 +0900 Subject: RFR: JDK-8163362-Reconsider reflection usage in java.awt.font.JavaAWTFontAccessImpl class In-Reply-To: <29344508-a30c-1920-d972-d25262d5311d@oracle.com> References: <29344508-a30c-1920-d972-d25262d5311d@oracle.com> Message-ID: <052b377b-ef54-3c50-b327-e7e0ee028abe@oracle.com> Looks good to me. Masayoshi On 8/22/2016 1:26 PM, Rachna Goel wrote: > Hi, > > Please review fix for JDK-8163362. > > https://bugs.openjdk.java.net/browse/JDK-8163362 > > Webrev: http://cr.openjdk.java.net/~rgoel/JDK-8163362/webrev.01/ > > This is a cleanup fix in which Reflection usage in > JavaAWTFontAccessImpl class was removed. > > Thanks, > > Rachna > From naoto.sato at oracle.com Mon Aug 22 15:15:07 2016 From: naoto.sato at oracle.com (Naoto Sato) Date: Mon, 22 Aug 2016 08:15:07 -0700 Subject: RFR: JDK-8163362-Reconsider reflection usage in java.awt.font.JavaAWTFontAccessImpl class In-Reply-To: <29344508-a30c-1920-d972-d25262d5311d@oracle.com> References: <29344508-a30c-1920-d972-d25262d5311d@oracle.com> Message-ID: Looks good. Naoto On 8/21/16 9:26 PM, Rachna Goel wrote: > Hi, > > Please review fix for JDK-8163362. > > https://bugs.openjdk.java.net/browse/JDK-8163362 > > Webrev: http://cr.openjdk.java.net/~rgoel/JDK-8163362/webrev.01/ > > This is a cleanup fix in which Reflection usage in JavaAWTFontAccessImpl > class was removed. > > Thanks, > > Rachna > From yuka.kamiya at oracle.com Tue Aug 23 07:23:57 2016 From: yuka.kamiya at oracle.com (Yuka Kamiya) Date: Tue, 23 Aug 2016 16:23:57 +0900 Subject: RFR: JDK-8150710: java/util/Locale/LocaleProviders.sh fails with RuntimeException: Format failed Message-ID: <47c06b0e-875b-739f-d483-92225cd27d41@oracle.com> Hello, http://cr.openjdk.java.net/~peytoia/7068008/webrev.00/ Please review a simple fix for: https://bugs.openjdk.java.net/browse/JDK-8150710 The change is to make a testdata generator use ASCII digits. Thanks, -- Yuka From yuka.kamiya at oracle.com Tue Aug 23 07:46:06 2016 From: yuka.kamiya at oracle.com (Yuka Kamiya) Date: Tue, 23 Aug 2016 16:46:06 +0900 Subject: RFR: JDK-8150710: java/util/Locale/LocaleProviders.sh fails with RuntimeException: Format failed In-Reply-To: <47c06b0e-875b-739f-d483-92225cd27d41@oracle.com> References: <47c06b0e-875b-739f-d483-92225cd27d41@oracle.com> Message-ID: Sorry, I used a wrong url... Correct location is http://cr.openjdk.java.net/~peytoia/8150710/webrev.00/ Thanks, -- Yuka On 2016/08/23 16:23, Yuka Kamiya wrote: > Hello, > > http://cr.openjdk.java.net/~peytoia/7068008/webrev.00/ > > Please review a simple fix for: > https://bugs.openjdk.java.net/browse/JDK-8150710 > > The change is to make a testdata generator use ASCII digits. > > Thanks, > -- > Yuka From masayoshi.okutsu at oracle.com Tue Aug 30 04:45:20 2016 From: masayoshi.okutsu at oracle.com (Masayoshi Okutsu) Date: Tue, 30 Aug 2016 13:45:20 +0900 Subject: RFR: 8157792: After Integrating tzdata2016d the test/sun/util/calendar/zi/TestZoneInfo310.java fails for "Asia/Oral" and "Asia/Qyzylorda" Timezones Message-ID: Hi, Please review the fix for JDK-8157792. When a zone item wasn't used for any standard-daylight transition, the zone information was discarded. Therefore, its GMT offset change wasn't taken. Issue: https://bugs.openjdk.java.net/browse/JDK-8157792 Webrev: http://cr.openjdk.java.net/~okutsu/9/8157792/webrev.00 Thanks, Masayoshi From yuka.kamiya at oracle.com Tue Aug 30 04:58:18 2016 From: yuka.kamiya at oracle.com (Yuka Kamiya) Date: Tue, 30 Aug 2016 13:58:18 +0900 Subject: RFR: 8157792: After Integrating tzdata2016d the test/sun/util/calendar/zi/TestZoneInfo310.java fails for "Asia/Oral" and "Asia/Qyzylorda" Timezones In-Reply-To: References: Message-ID: <806a2450-f264-ef20-566d-9dadddd978b4@oracle.com> Hi, The fix looks good to me. Thanks, -- Yuka On 2016/08/30 13:45, Masayoshi Okutsu wrote: > Hi, > > Please review the fix for JDK-8157792. When a zone item wasn't used > for any standard-daylight transition, the zone information was > discarded. Therefore, its GMT offset change wasn't taken. > > Issue: > https://bugs.openjdk.java.net/browse/JDK-8157792 > > Webrev: > http://cr.openjdk.java.net/~okutsu/9/8157792/webrev.00 > > Thanks, > Masayoshi >