diff --git a/src/java.logging/share/classes/java/util/logging/ErrorManager.java b/src/java.logging/share/classes/java/util/logging/ErrorManager.java index db654672ea3..ac3238688e0 100644 --- a/src/java.logging/share/classes/java/util/logging/ErrorManager.java +++ b/src/java.logging/share/classes/java/util/logging/ErrorManager.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2023, 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 @@ -85,13 +85,15 @@ public class ErrorManager { * @param ex an exception (may be null) * @param code an error code defined in ErrorManager */ - public synchronized void error(String msg, Exception ex, int code) { - if (reported) { - // We only report the first error, to avoid clogging - // the screen. - return; + public void error(String msg, Exception ex, int code) { + synchronized (this) { + if (reported) { + // We only report the first error, to avoid clogging + // the screen. + return; + } + reported = true; } - reported = true; String text = "java.util.logging.ErrorManager: " + code; if (msg != null) { text = text + ": " + msg; diff --git a/src/java.logging/share/classes/java/util/logging/FileHandler.java b/src/java.logging/share/classes/java/util/logging/FileHandler.java index 1bbc299bb94..e4ab1d71b2b 100644 --- a/src/java.logging/share/classes/java/util/logging/FileHandler.java +++ b/src/java.logging/share/classes/java/util/logging/FileHandler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2023, 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 @@ -728,7 +728,21 @@ public class FileHandler extends StreamHandler { /** * Rotate the set of output files */ - private synchronized void rotate() { + private void rotate() { + if (tryUseLock()) { + try { + rotate0(); + } finally { + unlock(); + } + } else { + synchronized (this) { + rotate0(); + } + } + } + + private void rotate0() { Level oldLevel = getLevel(); setLevel(Level.OFF); @@ -760,9 +774,23 @@ public class FileHandler extends StreamHandler { * @param record description of the log event. A null record is * silently ignored and is not published */ - @SuppressWarnings("removal") @Override - public synchronized void publish(LogRecord record) { + public void publish(LogRecord record) { + if (tryUseLock()) { + try { + publish0(record); + } finally { + unlock(); + } + } else { + synchronized (this) { + publish0(record); + } + } + + } + @SuppressWarnings("removal") + private void publish0(LogRecord record) { if (!isLoggable(record)) { return; } @@ -791,7 +819,21 @@ public class FileHandler extends StreamHandler { * the caller does not have {@code LoggingPermission("control")}. */ @Override - public synchronized void close() throws SecurityException { + public void close() throws SecurityException { + if (tryUseLock()) { + try { + close0(); + } finally { + unlock(); + } + } else { + synchronized (this) { + close0(); + } + } + } + + private void close0() throws SecurityException { super.close(); // Unlock any lock file. if (lockFileName == null) { diff --git a/src/java.logging/share/classes/java/util/logging/Handler.java b/src/java.logging/share/classes/java/util/logging/Handler.java index 753f53663e2..cf7d9bc2256 100644 --- a/src/java.logging/share/classes/java/util/logging/Handler.java +++ b/src/java.logging/share/classes/java/util/logging/Handler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2023, 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 @@ -30,6 +30,7 @@ import java.util.Objects; import java.io.UnsupportedEncodingException; import java.security.AccessController; import java.security.PrivilegedAction; +import java.util.concurrent.locks.ReentrantLock; /** * A {@code Handler} object takes log messages from a {@code Logger} and @@ -65,6 +66,7 @@ public abstract class Handler { private volatile Level logLevel = Level.ALL; private volatile ErrorManager errorManager = new ErrorManager(); private volatile String encoding; + private final ReentrantLock lock; /** * Default constructor. The resulting {@code Handler} has a log @@ -73,6 +75,17 @@ public abstract class Handler { * as the {@code ErrorManager}. */ protected Handler() { + lock = initLocking(); + } + + private ReentrantLock initLocking() { + Class clazz = this.getClass(); + ClassLoader loader = clazz.getClassLoader(); + if (loader != null && loader != ClassLoader.getPlatformClassLoader()) { + return null; + } else { + return new ReentrantLock(); + } } /** @@ -90,6 +103,7 @@ public abstract class Handler { @SuppressWarnings("removal") Handler(Level defaultLevel, Formatter defaultFormatter, Formatter specifiedFormatter) { + this(); LogManager manager = LogManager.getLogManager(); String cname = getClass().getName(); @@ -122,6 +136,15 @@ public abstract class Handler { }, null, LogManager.controlPermission); } + boolean tryUseLock() { + if (lock == null) return false; + lock.lock(); + return true; + } + void unlock() { + lock.unlock(); + } + /** * Publish a {@code LogRecord}. *

@@ -165,7 +188,21 @@ public abstract class Handler { * @throws SecurityException if a security manager exists and if * the caller does not have {@code LoggingPermission("control")}. */ - public synchronized void setFormatter(Formatter newFormatter) throws SecurityException { + public void setFormatter(Formatter newFormatter) throws SecurityException { + if (tryUseLock()) { + try { + setFormatter0(newFormatter); + } finally { + unlock(); + } + } else { + synchronized (this) { + setFormatter0(newFormatter); + } + } + } + + private void setFormatter0(Formatter newFormatter) throws SecurityException { checkPermission(); formatter = Objects.requireNonNull(newFormatter); } @@ -191,7 +228,22 @@ public abstract class Handler { * @throws UnsupportedEncodingException if the named encoding is * not supported. */ - public synchronized void setEncoding(String encoding) + public void setEncoding(String encoding) + throws SecurityException, java.io.UnsupportedEncodingException { + if (tryUseLock()) { + try { + setEncoding0(encoding); + } finally { + unlock(); + } + } else { + synchronized (this) { + setEncoding0(encoding); + } + } + } + + private void setEncoding0(String encoding) throws SecurityException, java.io.UnsupportedEncodingException { checkPermission(); if (encoding != null) { @@ -227,7 +279,21 @@ public abstract class Handler { * @throws SecurityException if a security manager exists and if * the caller does not have {@code LoggingPermission("control")}. */ - public synchronized void setFilter(Filter newFilter) throws SecurityException { + public void setFilter(Filter newFilter) throws SecurityException { + if (tryUseLock()) { + try { + setFilter0(newFilter); + } finally { + unlock(); + } + } else { + synchronized (this) { + setFilter0(newFilter); + } + } + } + + private void setFilter0(Filter newFilter) throws SecurityException { checkPermission(); filter = newFilter; } @@ -251,7 +317,21 @@ public abstract class Handler { * @throws SecurityException if a security manager exists and if * the caller does not have {@code LoggingPermission("control")}. */ - public synchronized void setErrorManager(ErrorManager em) { + public void setErrorManager(ErrorManager em) { + if (tryUseLock()) { + try { + setErrorManager0(em); + } finally { + unlock(); + } + } else { + synchronized (this) { + setErrorManager0(em); + } + } + } + + private void setErrorManager0(ErrorManager em) { checkPermission(); if (em == null) { throw new NullPointerException(); @@ -303,7 +383,21 @@ public abstract class Handler { * @throws SecurityException if a security manager exists and if * the caller does not have {@code LoggingPermission("control")}. */ - public synchronized void setLevel(Level newLevel) throws SecurityException { + public void setLevel(Level newLevel) throws SecurityException { + if (tryUseLock()) { + try { + setLevel0(newLevel); + } finally { + unlock(); + } + } else { + synchronized (this) { + setLevel0(newLevel); + } + } + } + + private void setLevel0(Level newLevel) throws SecurityException { if (newLevel == null) { throw new NullPointerException(); } @@ -311,6 +405,8 @@ public abstract class Handler { logLevel = newLevel; } + + /** * Get the log level specifying which messages will be * logged by this {@code Handler}. Message levels lower diff --git a/src/java.logging/share/classes/java/util/logging/MemoryHandler.java b/src/java.logging/share/classes/java/util/logging/MemoryHandler.java index fbf421391cf..e5716426078 100644 --- a/src/java.logging/share/classes/java/util/logging/MemoryHandler.java +++ b/src/java.logging/share/classes/java/util/logging/MemoryHandler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2023, 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 @@ -178,7 +178,21 @@ public class MemoryHandler extends Handler { * silently ignored and is not published */ @Override - public synchronized void publish(LogRecord record) { + public void publish(LogRecord record) { + if (tryUseLock()) { + try { + publish0(record); + } finally { + unlock(); + } + } else { + synchronized (this) { + publish0(record); + } + } + } + + private void publish0(LogRecord record) { if (!isLoggable(record)) { return; } @@ -200,7 +214,21 @@ public class MemoryHandler extends Handler { *

* The buffer is then cleared. */ - public synchronized void push() { + public void push() { + if (tryUseLock()) { + try { + push0(); + } finally { + unlock(); + } + } else { + synchronized (this) { + push0(); + } + } + } + + private void push0() { for (int i = 0; i < count; i++) { int ix = (start+i)%buffer.length; LogRecord record = buffer[ix]; @@ -244,7 +272,21 @@ public class MemoryHandler extends Handler { * @throws SecurityException if a security manager exists and if * the caller does not have {@code LoggingPermission("control")}. */ - public synchronized void setPushLevel(Level newLevel) throws SecurityException { + public void setPushLevel(Level newLevel) throws SecurityException { + if (tryUseLock()) { + try { + setPushLevel0(newLevel); + } finally { + unlock(); + } + } else { + synchronized (this) { + setPushLevel0(newLevel); + } + } + } + + private void setPushLevel0(Level newLevel) throws SecurityException { if (newLevel == null) { throw new NullPointerException(); } diff --git a/src/java.logging/share/classes/java/util/logging/SocketHandler.java b/src/java.logging/share/classes/java/util/logging/SocketHandler.java index 39f2e272016..edf53144451 100644 --- a/src/java.logging/share/classes/java/util/logging/SocketHandler.java +++ b/src/java.logging/share/classes/java/util/logging/SocketHandler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2023, 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 @@ -156,7 +156,21 @@ public class SocketHandler extends StreamHandler { * the caller does not have {@code LoggingPermission("control")}. */ @Override - public synchronized void close() throws SecurityException { + public void close() throws SecurityException { + if (tryUseLock()) { + try { + close0(); + } finally { + unlock(); + } + } else { + synchronized (this) { + close0(); + } + } + } + + private void close0() throws SecurityException { super.close(); if (sock != null) { try { @@ -175,7 +189,21 @@ public class SocketHandler extends StreamHandler { * silently ignored and is not published */ @Override - public synchronized void publish(LogRecord record) { + public void publish(LogRecord record) { + if (tryUseLock()) { + try { + publish0(record); + } finally { + unlock(); + } + } else { + synchronized (this) { + publish0(record); + } + } + } + + private void publish0(LogRecord record) { if (!isLoggable(record)) { return; } diff --git a/src/java.logging/share/classes/java/util/logging/StreamHandler.java b/src/java.logging/share/classes/java/util/logging/StreamHandler.java index 4ec88cc5908..320638d91a1 100644 --- a/src/java.logging/share/classes/java/util/logging/StreamHandler.java +++ b/src/java.logging/share/classes/java/util/logging/StreamHandler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2023, 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 @@ -122,7 +122,21 @@ public class StreamHandler extends Handler { * @throws SecurityException if a security manager exists and if * the caller does not have {@code LoggingPermission("control")}. */ - protected synchronized void setOutputStream(OutputStream out) throws SecurityException { + protected void setOutputStream(OutputStream out) throws SecurityException { + if (tryUseLock()) { + try { + setOutputStream0(out); + } finally { + unlock(); + } + } else { + synchronized (this) { + setOutputStream0(out); + } + } + } + + private void setOutputStream0(OutputStream out) throws SecurityException { if (out == null) { throw new NullPointerException(); } @@ -157,7 +171,21 @@ public class StreamHandler extends Handler { * not supported. */ @Override - public synchronized void setEncoding(String encoding) + public void setEncoding(String encoding) + throws SecurityException, java.io.UnsupportedEncodingException { + if (tryUseLock()) { + try { + setEncoding0(encoding); + } finally { + unlock(); + } + } else { + synchronized (this) { + setEncoding0(encoding); + } + } + } + private void setEncoding0(String encoding) throws SecurityException, java.io.UnsupportedEncodingException { super.setEncoding(encoding); if (output == null) { @@ -190,7 +218,20 @@ public class StreamHandler extends Handler { * silently ignored and is not published */ @Override - public synchronized void publish(LogRecord record) { + public void publish(LogRecord record) { + if (tryUseLock()) { + try { + publish0(record); + } finally { + unlock(); + } + } else { + synchronized (this) { + publish0(record); + } + } + } + private void publish0(LogRecord record) { if (!isLoggable(record)) { return; } @@ -241,7 +282,20 @@ public class StreamHandler extends Handler { * Flush any buffered messages. */ @Override - public synchronized void flush() { + public void flush() { + if (tryUseLock()) { + try { + flush0(); + } finally { + unlock(); + } + } else { + synchronized (this) { + flush0(); + } + } + } + private void flush0() { if (writer != null) { try { writer.flush(); @@ -253,7 +307,7 @@ public class StreamHandler extends Handler { } } - private synchronized void flushAndClose() throws SecurityException { + private void flushAndClose() throws SecurityException { checkPermission(); if (writer != null) { try { @@ -286,8 +340,18 @@ public class StreamHandler extends Handler { * the caller does not have LoggingPermission("control"). */ @Override - public synchronized void close() throws SecurityException { - flushAndClose(); + public void close() throws SecurityException { + if (tryUseLock()) { + try { + flushAndClose(); + } finally { + unlock(); + } + } else { + synchronized (this) { + flushAndClose(); + } + } } // Package-private support for setting OutputStream