JDK-8005899 : Logger.getLogger(name, null) should not allow to reset a non-null resource bundle
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.util.logging
  • Affected Version: 8
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • Submitted: 2013-01-09
  • Updated: 2013-09-09
  • Resolved: 2013-08-23
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 8
8 b106Fixed
Related Reports
Relates :  
Description
Below shows the test case that passes with JDK 7 but fails with JDK8.

If a logger of a given name exists, Logger.getLogger(name, null) throws IAE when running with JDK 7.  Looks like this is related to the fix for JDK-7045594 in JDK 8 [1].

[1] http://hg.openjdk.java.net/jdk8/tl/jdk/rev/4a221501079a

----------------------------------------------------------------
import java.util.logging.*;
import java.util.*;

public class TestLogger {

    public static final String RESOURCE_BUNDLE = "myresource";
    public static final String FOO_LOGGER = "org.foo.Foo";
    public static final String BAR_LOGGER = "org.bar.Bar";
    public static final String GEE_LOGGER = "org.gee.Gee";

    public static void main(String[] args) {
        newLogger(FOO_LOGGER, RESOURCE_BUNDLE);
        newLogger(FOO_LOGGER);
        newLogger(BAR_LOGGER);
        newLogger(BAR_LOGGER, RESOURCE_BUNDLE);
        newLogger(GEE_LOGGER, null);
        newLogger(GEE_LOGGER, RESOURCE_BUNDLE);
        try {
            Logger.getLogger(GEE_LOGGER, null);
            throw new RuntimeException("Shouldn't allow to reset the resource bundle");
        } catch (IllegalArgumentException e) {}
    }

    private static List<Logger> strongRefs = new ArrayList<>();
    private static void newLogger(String name) {
        strongRefs.add(Logger.getLogger(name));
    }
    private static void newLogger(String name, String resourceBundleName) {
        strongRefs.add(Logger.getLogger(name, resourceBundleName));
    }
}
Comments
If we wanted to fix Logger.getLogger(loggername, null) to behave like in 7 I think we would have to modify Logger.getLogger(loggername, rbname), so that it throws IAE at posteriori if logger has a non null rbname and rbname is null. + I think we would need to clarify the spec on the meaning of passing 'null'. Anyway here is a modified version of the test provided above - which shows that the resource bundle has not been reset. It shows that in JDK8 Logger.getLogger(name) and Logger.getLogger(name, null) are equivalent. package testlogmanager; import java.util.ArrayList; import java.util.List; import java.util.logging.Logger; public class TestLogger { public static final String RESOURCE_BUNDLE = "testlogmanager.MyResource"; public static final String FOO_LOGGER = "org.foo.Foo"; public static final String BAR_LOGGER = "org.bar.Bar"; public static final String GEE_LOGGER = "org.gee.Gee"; public static void main(String[] args) { newLogger(FOO_LOGGER, RESOURCE_BUNDLE); newLogger(FOO_LOGGER); newLogger(BAR_LOGGER); newLogger(BAR_LOGGER, RESOURCE_BUNDLE); newLogger(GEE_LOGGER, null); newLogger(GEE_LOGGER, RESOURCE_BUNDLE); if (!RESOURCE_BUNDLE.equals(Logger.getLogger(GEE_LOGGER).getResourceBundleName())) { throw new RuntimeException("Shouldn't allow to reset the resource bundle"); } try { Logger.getLogger(GEE_LOGGER, null); if (!RESOURCE_BUNDLE.equals(Logger.getLogger(GEE_LOGGER).getResourceBundleName())) { throw new RuntimeException("Shouldn't allow to reset the resource bundle"); } } catch (IllegalArgumentException e) {} } private static List<Logger> strongRefs = new ArrayList<>(); private static void newLogger(String name) { strongRefs.add(Logger.getLogger(name)); } private static void newLogger(String name, String resourceBundleName) { strongRefs.add(Logger.getLogger(name, resourceBundleName)); } }
27-06-2013

Here is the reason why I consider it a bug: The specification of Logger.getLogger(String name, String resourceBundleName) says: If the named Logger already exists and does not yet have a localization resource bundle then the given resource bundle name is used. If the named Logger already exists and has a different resource bundle name then an IllegalArgumentException is thrown. Logger.getLogger("foo") is not equivalent to Logger.getLogger("foo", null) in my opinion. Logger.getLogger("foo", rbname) is specified to configure the resource bundle of the "foo" logger if it's not set. A logger's resource bundle can be set to non-null only once (and it throws MissingResourceBundleException if the given rbname is invalid). Consider: Thread A calls Logger.getLogger("foo", "myresource"); Thread B calls Logger.getLogger("foo", null); Thread C calls Logger.getLogger("foo", "another); What should Thread B expect? which resource bundle does Thread B expect the foo logger use? Logger.getLogger("foo") has a clear semantics that use the "foo" logger with any resource bundle registered. If Logger.getLogger("foo", null) returns successfully but the foo logger is using "myresource", the messages will be localized. As a side note - it seems that the Logger.setResourceBundle method is missing and Logger.getLogger(name, rbname) is essentially equivalent to Logger.getLogger(name).setResourceBundle(rbname).
26-06-2013

Hi Mandy - I am not sure I understand this bug. If I look at the code in JDK8 I see that 'null' is being ignored. setUpResourceInfo(name, ...) does: if (name == null) { return; } This makes sense as it means that Logger.getLogger(somename) is equivalent to Logger.getLogger(somename, null); I do not see this as an issue. It is however a change of behavior compared with 7. The spec of getLogger() is rather vague about what resourceBundleName==null exactly means - and it probably needs to be clarified. My feeling is that JDK8 does the correct thing (ignoring null) and JDK7 has a bug (it throws an IAE when the logger already has a RB and null is passed)... We could try to make JDK8 throw an exception like JDK7 but this wouldn't go in favor of a simplification of the API. Whatever we decide to do (make JDK7 behave as JDK8 or make JDK8 behave as JDK7) we will still need to clarify the spec. Today the spec says (both in 7 and 8 - I am not seeing any difference): @param resourceBundleName name of ResourceBundle to be used for localizing messages for this logger. May be <CODE>null</CODE> if none of the messages require localization. @throws IllegalArgumentException if the Logger already exists and uses a different resource bundle name. JDK7 interprets 'null' as being different from the logger's resource bundle name when the logger's resource bundle name is not null, and therefore it throws IAE JDK8 interprets 'null' as indicating that the caller doesn't care about the resource bundle because none of its messages will require localization, and therefore it simply ignore null and leaves the logger's resource bundle unchanged. If I had to vote, I would choose JDK8 interpretation. But would that be considered as an incompatible change?
26-06-2013