fix logger command print parent ClassLoader result problem. #870

pull/882/head
hengyunabc 5 years ago
parent 7950027113
commit f9e698d09c

@ -0,0 +1,43 @@
package com.taobao.arthas.core.command.logger;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.commons.ClassRemapper;
import org.objectweb.asm.commons.Remapper;
import org.objectweb.asm.commons.SimpleRemapper;
/**
*
* @author hengyunabc 2019-09-23
*
*/
public class AsmRenameUtil {
public static byte[] renameClass(byte[] bytes, final String oldName, final String newName) {
ClassReader reader = new ClassReader(bytes);
ClassWriter writer = new ClassWriter(reader, 0);
final String internalOldName = oldName.replace('.', '/');
final String internalNewName = newName.replace('.', '/');
// ClassVisitor visitor = new ClassRemapper(writer, new Remapper() {
//
// @Override
// public String mapType(String internalName) {
// if (internalName.equals(internalOldName)) {
// return internalNewName;
// } else {
// return super.mapType(internalName);
// }
// }
//
// });
ClassVisitor visitor = new ClassRemapper(writer, new SimpleRemapper(internalOldName, internalNewName));
reader.accept(visitor, 0);
return writer.toByteArray();
}
}

@ -19,6 +19,8 @@ import org.apache.logging.log4j.core.appender.FileAppender;
import org.apache.logging.log4j.core.config.Configuration;
import org.apache.logging.log4j.core.config.LoggerConfig;
import com.taobao.arthas.core.util.StringUtils;
/**
*
* @author hengyunabc 2019-09-20
@ -30,7 +32,7 @@ public class Log4j2Helper {
static {
try {
Class<?> loggerClass = Class.forName("org.apache.logging.log4j.Logger");
Class<?> loggerClass = Log4j2Helper.class.getClassLoader().loadClass("org.apache.logging.log4j.Logger");
// 这里可能会加载到其它上游ClassLoader的log4j2因此需要判断是否当前classloader
if (loggerClass.getClassLoader().equals(Log4j2Helper.class.getClassLoader())) {
Log4j2 = true;
@ -93,6 +95,10 @@ public class Log4j2Helper {
if (loggerConfig == null) {
return loggerInfoMap;
}
// 排掉非root时获取到root的logger config
if (!name.equalsIgnoreCase(LoggerConfig.ROOT) && StringUtils.isEmpty(loggerConfig.getName())) {
return loggerInfoMap;
}
loggerInfoMap.put(name, doGetLoggerInfo(loggerConfig));
} else {
// 获取所有logger时如果没有appender则忽略

@ -26,7 +26,7 @@ public class Log4jHelper {
static {
try {
Class<?> loggerClass = Class.forName("org.apache.log4j.Logger");
Class<?> loggerClass = Log4jHelper.class.getClassLoader().loadClass("org.apache.log4j.Logger");
// 这里可能会加载到其它上游ClassLoader的log4j因此需要判断是否当前classloader
if (loggerClass.getClassLoader().equals(Log4jHelper.class.getClassLoader())) {
Log4j = true;
@ -129,6 +129,10 @@ public class Log4jHelper {
private static List<Map<String, Object>> doGetLoggerAppenders(Enumeration<Appender> appenders) {
List<Map<String, Object>> result = new ArrayList<Map<String, Object>>();
if (appenders == null) {
return result;
}
while (appenders.hasMoreElements()) {
Map<String, Object> info = new HashMap<String, Object>();
Appender appender = appenders.nextElement();
@ -143,7 +147,9 @@ public class Log4jHelper {
info.put(LoggerHelper.target, ((ConsoleAppender) appender).getTarget());
} else if (appender instanceof AsyncAppender) {
@SuppressWarnings("unchecked")
List<Map<String, Object>> asyncs = doGetLoggerAppenders(((AsyncAppender) appender).getAllAppenders());
Enumeration<Appender> appendersOfAsync = ((AsyncAppender) appender).getAllAppenders();
if (appendersOfAsync != null) {
List<Map<String, Object>> asyncs = doGetLoggerAppenders(appendersOfAsync);
// 标明异步appender
List<String> appenderRef = new ArrayList<String>();
for (Map<String, Object> a : asyncs) {
@ -154,6 +160,7 @@ public class Log4jHelper {
info.put(LoggerHelper.appenderRef, appenderRef);
}
}
}
return result;
}

@ -34,7 +34,7 @@ public class LogbackHelper {
static {
try {
Class<?> loggerClass = Class.forName("ch.qos.logback.classic.Logger");
Class<?> loggerClass = LogbackHelper.class.getClassLoader().loadClass("ch.qos.logback.classic.Logger");
// 这里可能会加载到应用中依赖的logback因此需要判断classloader
if (loggerClass.getClassLoader().equals(LogbackHelper.class.getClassLoader())) {
ILoggerFactory loggerFactory = org.slf4j.LoggerFactory.getILoggerFactory();

@ -41,8 +41,8 @@ import com.taobao.text.util.RenderUtil;
*/
@Name("logger")
@Summary("Print logger info, and update the logger level")
@Description("\nExamples:\n" + " logger\n" + " logger -c 327a647b\n" + " logger -c 327a647b --name ROOT --level debug\n"
+ Constants.WIKI + Constants.WIKI_HOME + "logger")
@Description("\nExamples:\n" + " logger\n" + " logger -c 327a647b\n"
+ " logger -c 327a647b --name ROOT --level debug\n" + Constants.WIKI + Constants.WIKI_HOME + "logger")
public class LoggerCommand extends AnnotatedCommand {
private static final Logger logger = LogUtil.getArthasLogger();
@ -53,6 +53,9 @@ public class LoggerCommand extends AnnotatedCommand {
private static Map<Class<?>, byte[]> classToBytesMap = new HashMap<Class<?>, byte[]>();
private static String arthasClassLoaderHash = ClassLoaderUtils
.classLoaderHash(LoggerCommand.class.getClassLoader());
static {
LoggerHelperBytes = loadClassBytes(LoggerHelper.class);
Log4jHelperBytes = loadClassBytes(Log4jHelper.class);
@ -278,7 +281,8 @@ public class LoggerCommand extends AnnotatedCommand {
label("" + appenderInfo.get(LoggerHelper.target)));
}
if (appenderInfo.get(LoggerHelper.blocking) != null) {
appendersTable.row(label(LoggerHelper.blocking), label("" + appenderInfo.get(LoggerHelper.blocking)));
appendersTable.row(label(LoggerHelper.blocking),
label("" + appenderInfo.get(LoggerHelper.blocking)));
}
if (appenderInfo.get(LoggerHelper.appenderRef) != null) {
appendersTable.row(label(LoggerHelper.appenderRef),
@ -294,21 +298,33 @@ public class LoggerCommand extends AnnotatedCommand {
return sb.toString();
}
private static String helperClassNameWithClassLoader(ClassLoader classLoader, Class<?> helperClass) {
String classLoaderHash = ClassLoaderUtils.classLoaderHash(classLoader);
String className = helperClass.getName();
// if want to debug, change to return className
return className + arthasClassLoaderHash + classLoaderHash;
}
@SuppressWarnings("unchecked")
private Map<String, Map<String, Object>> loggerInfo(ClassLoader classLoader, Class<?> helperClass) {
Map<String, Map<String, Object>> loggers = Collections.emptyMap();
String helperClassName = helperClassNameWithClassLoader(classLoader, helperClass);
try {
classLoader.loadClass(helperClass.getName());
classLoader.loadClass(helperClassName);
} catch (ClassNotFoundException e) {
try {
ReflectUtils.defineClass(helperClass.getName(), classToBytesMap.get(helperClass), classLoader);
} catch (Exception e1) {
// ignore
byte[] helperClassBytes = AsmRenameUtil.renameClass(classToBytesMap.get(helperClass),
helperClass.getName(), helperClassName);
ReflectUtils.defineClass(helperClassName, helperClassBytes, classLoader);
} catch (Throwable e1) {
logger.error("arthas", "arthas loggger command try to define helper class error: " + helperClassName,
e1);
}
}
try {
Class<?> clazz = classLoader.loadClass(helperClass.getName());
Class<?> clazz = classLoader.loadClass(helperClassName);
Method getLoggersMethod = clazz.getMethod("getLoggers", new Class<?>[] { String.class, boolean.class });
loggers = (Map<String, Map<String, Object>>) getLoggersMethod.invoke(null,
new Object[] { name, includeNoAppender });
@ -326,7 +342,7 @@ public class LoggerCommand extends AnnotatedCommand {
classLoader = ClassLoaderUtils.getClassLoader(inst, hashCode);
}
Class<?> clazz = classLoader.loadClass(helperClass.getName());
Class<?> clazz = classLoader.loadClass(helperClassNameWithClassLoader(classLoader, helperClass));
Method updateLevelMethod = clazz.getMethod("updateLevel", new Class<?>[] { String.class, String.class });
return (Boolean) updateLevelMethod.invoke(null, new Object[] { this.name, this.level });

@ -38,4 +38,20 @@ public class ClassLoaderUtils {
}
return null;
}
public static String classLoaderHash(ClassLoader classLoader) {
int hashCode = 0;
if (classLoader == null) {
hashCode = System.identityHashCode(classLoader);
} else {
hashCode = classLoader.hashCode();
}
if (hashCode <= 0) {
hashCode = System.identityHashCode(classLoader);
if (hashCode < 0) {
hashCode = -hashCode;
}
}
return Integer.toHexString(hashCode);
}
}

Loading…
Cancel
Save