8216363: NullPointerException in java.util.logging.Handler#isLoggable
Summary: The implementation is changed to match the spec: isLoggable(null) returns false.
Reviewed-by: mchung, lancea
--- a/src/java.logging/share/classes/java/util/logging/Handler.java Mon Feb 18 17:41:31 2019 +0100
+++ b/src/java.logging/share/classes/java/util/logging/Handler.java Thu Feb 21 16:57:47 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -329,12 +329,13 @@
* handler from logging the {@code LogRecord}. It will return false if
* the {@code LogRecord} is null.
*
- * @param record a {@code LogRecord}
+ * @param record a {@code LogRecord} (may be null).
* @return true if the {@code LogRecord} would be logged.
*
*/
public boolean isLoggable(LogRecord record) {
final int levelValue = getLevel().intValue();
+ if (record == null) return false;
if (record.getLevel().intValue() < levelValue || levelValue == offValue) {
return false;
}
--- a/src/java.logging/share/classes/java/util/logging/MemoryHandler.java Mon Feb 18 17:41:31 2019 +0100
+++ b/src/java.logging/share/classes/java/util/logging/MemoryHandler.java Thu Feb 21 16:57:47 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -270,7 +270,7 @@
* check whether the {@code LogRecord} would result in a "push" of the
* buffer contents. It will return false if the {@code LogRecord} is null.
*
- * @param record a {@code LogRecord}
+ * @param record a {@code LogRecord} (may be null).
* @return true if the {@code LogRecord} would be logged.
*
*/
--- a/src/java.logging/share/classes/java/util/logging/StreamHandler.java Mon Feb 18 17:41:31 2019 +0100
+++ b/src/java.logging/share/classes/java/util/logging/StreamHandler.java Thu Feb 21 16:57:47 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -225,7 +225,7 @@
* whether it satisfies any {@code Filter}. It will also return false if
* no output stream has been assigned yet or the LogRecord is null.
*
- * @param record a {@code LogRecord}
+ * @param record a {@code LogRecord} (may be null).
* @return true if the {@code LogRecord} would be logged.
*
*/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/util/logging/IsLoggableHandlerTest.java Thu Feb 21 16:57:47 2019 +0000
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8216363
+ * @summary Test that Handler.isLoggable(null) returns false
+ * @run main/othervm IsLoggableHandlerTest
+ */
+import java.io.File;
+import java.io.IOException;
+import java.util.UUID;
+import java.util.logging.ConsoleHandler;
+import java.util.logging.FileHandler;
+import java.util.logging.Handler;
+import java.util.logging.Level;
+import java.util.logging.LogRecord;
+import java.util.logging.MemoryHandler;
+import java.util.logging.StreamHandler;
+import java.util.stream.Stream;
+
+public class IsLoggableHandlerTest {
+
+
+ public static void main(String... args) throws IOException {
+ String userDir = System.getProperty("user.dir", ".");
+ File logfile = new File(userDir, "IsLoggableHandlerTest_" + UUID.randomUUID() + ".log");
+ try {
+ System.out.println("Dummy logfile: " + logfile.getAbsolutePath());
+ Handler h = new CustomHandler();
+ testIsLoggable(h);
+ testIsLoggable(new MemoryHandler(h, 1, Level.ALL));
+ testIsLoggable(new StreamHandler(System.out, new java.util.logging.SimpleFormatter()));
+ testIsLoggable(new FileHandler(logfile.getAbsolutePath()));
+ testIsLoggable(new ConsoleHandler());
+ } finally {
+ if (logfile.canRead()) {
+ try {
+ System.out.println("Deleting dummy logfile: " + logfile.getAbsolutePath());
+ logfile.delete();
+ } catch (Throwable t) {
+ System.out.println("Warning: failed to delete dummy logfile: " + t);
+ t.printStackTrace();
+ }
+ }
+ }
+ }
+
+ public static void testIsLoggable(Handler h) {
+ System.out.println("Testing " + h.getClass().getName());
+ // should not throw NPE but return false
+ if (h.isLoggable(null)) {
+ throw new AssertionError(h.getClass().getName()
+ + ": null record should not be loggable");
+ }
+ h.setLevel(Level.ALL);
+ // should still not throw NPE but return false
+ if (h.isLoggable(null)) {
+ throw new AssertionError(h.getClass().getName()
+ + ": null record should not be loggable");
+ }
+ // should not throw NPE
+ h.publish(null);
+ }
+
+ public static final class CustomHandler extends Handler {
+ @Override
+ public void publish(LogRecord record) { }
+ @Override
+ public void flush() { }
+ @Override
+ public void close() throws SecurityException { }
+ }
+
+
+}