LOG4J2-1926 Remove references to java.lang.management package - make inner interface ThreadInfoFactory public - obtain ThreadInfoFactory instance from ServiceLoader, fall back to BasicThreadInfoFactory - move ExtendedThreadInfoFactory out of ThreadDumpMessage class
Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/d0023dee Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/d0023dee Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/d0023dee Branch: refs/heads/master Commit: d0023dee94ecee680ee3cdc0be31313337fd49ad Parents: a0fcb15 Author: rpopma <[email protected]> Authored: Sat Jun 24 19:52:48 2017 +0900 Committer: rpopma <[email protected]> Committed: Sat Jun 24 19:52:48 2017 +0900 ---------------------------------------------------------------------- .../log4j/message/ThreadDumpMessage.java | 71 +++++++++----------- 1 file changed, 30 insertions(+), 41 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/d0023dee/log4j-api/src/main/java/org/apache/logging/log4j/message/ThreadDumpMessage.java ---------------------------------------------------------------------- diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/message/ThreadDumpMessage.java b/log4j-api/src/main/java/org/apache/logging/log4j/message/ThreadDumpMessage.java index 4cf7478..4fd1347 100644 --- a/log4j-api/src/main/java/org/apache/logging/log4j/message/ThreadDumpMessage.java +++ b/log4j-api/src/main/java/org/apache/logging/log4j/message/ThreadDumpMessage.java @@ -19,13 +19,13 @@ package org.apache.logging.log4j.message; import java.io.InvalidObjectException; import java.io.ObjectInputStream; import java.io.Serializable; -import java.lang.management.ManagementFactory; -import java.lang.management.ThreadInfo; -import java.lang.management.ThreadMXBean; -import java.lang.reflect.Method; import java.util.HashMap; +import java.util.Iterator; import java.util.Map; +import java.util.ServiceConfigurationError; +import java.util.ServiceLoader; +import org.apache.logging.log4j.status.StatusLogger; import org.apache.logging.log4j.util.StringBuilderFormattable; import org.apache.logging.log4j.util.Strings; @@ -34,36 +34,20 @@ import org.apache.logging.log4j.util.Strings; */ @AsynchronouslyFormattable public class ThreadDumpMessage implements Message, StringBuilderFormattable { - private static final long serialVersionUID = -1103400781608841088L; - - private static final ThreadInfoFactory FACTORY; + private static ThreadInfoFactory FACTORY; private volatile Map<ThreadInformation, StackTraceElement[]> threads; - private final String title; - private String formattedMessage; - static { - final Method[] methods = ThreadInfo.class.getMethods(); - boolean basic = true; - for (final Method method : methods) { - if (method.getName().equals("getLockInfo")) { - basic = false; - break; - } - } - FACTORY = basic ? new BasicThreadInfoFactory() : new ExtendedThreadInfoFactory(); - } - /** * Generate a ThreadDumpMessage with a title. * @param title The title. */ public ThreadDumpMessage(final String title) { this.title = title == null ? Strings.EMPTY : title; - threads = FACTORY.createThreadInfo(); + threads = getFactory().createThreadInfo(); } private ThreadDumpMessage(final String formattedMsg, final String title) { @@ -71,6 +55,29 @@ public class ThreadDumpMessage implements Message, StringBuilderFormattable { this.title = title == null ? Strings.EMPTY : title; } + private static ThreadInfoFactory getFactory() { + if (FACTORY == null) { + FACTORY = initFactory(ThreadDumpMessage.class.getClassLoader()); + } + return FACTORY; + } + + private static ThreadInfoFactory initFactory(final ClassLoader classLoader) { + ServiceLoader<ThreadInfoFactory> serviceLoader = ServiceLoader.load(ThreadInfoFactory.class, classLoader); + ThreadInfoFactory result = null; + try { + Iterator<ThreadInfoFactory> iterator = serviceLoader.iterator(); + while (result == null && iterator.hasNext()) { + result = iterator.next(); + } + } catch (ServiceConfigurationError | LinkageError | Exception unavailable) { // if java management classes not available + StatusLogger.getLogger().info("ThreadDumpMessage uses BasicThreadInfoFactory: " + + "could not load extended ThreadInfoFactory: {}", unavailable.toString()); + result = null; + } + return result == null ? new BasicThreadInfoFactory() : result; + } + @Override public String toString() { return getFormattedMessage(); @@ -162,7 +169,7 @@ public class ThreadDumpMessage implements Message, StringBuilderFormattable { /** * Factory to create Thread information. */ - private interface ThreadInfoFactory { + public static interface ThreadInfoFactory { Map<ThreadInformation, StackTraceElement[]> createThreadInfo(); } @@ -183,24 +190,6 @@ public class ThreadDumpMessage implements Message, StringBuilderFormattable { } /** - * Factory to create extended thread information. - */ - private static class ExtendedThreadInfoFactory implements ThreadInfoFactory { - @Override - public Map<ThreadInformation, StackTraceElement[]> createThreadInfo() { - final ThreadMXBean bean = ManagementFactory.getThreadMXBean(); - final ThreadInfo[] array = bean.dumpAllThreads(true, true); - - final Map<ThreadInformation, StackTraceElement[]> threads = - new HashMap<>(array.length); - for (final ThreadInfo info : array) { - threads.put(new ExtendedThreadInformation(info), info.getStackTrace()); - } - return threads; - } - } - - /** * Always returns null. * * @return null
