mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 15:24:43 +02:00
8307535: java.util.logging.Handlers should be more VirtualThread friendly
Reviewed-by: jpai
This commit is contained in:
parent
9fa8b9a4a6
commit
3c68c352fc
6 changed files with 307 additions and 33 deletions
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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}.
|
||||
* <p>
|
||||
|
@ -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
|
||||
|
|
|
@ -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 {
|
|||
* <p>
|
||||
* 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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue