mirror of
https://github.com/alibaba/arthas.git
synced 2024-04-21 10:21:39 +00:00
add ognl command. #240
This commit is contained in:
@@ -15,6 +15,7 @@ import com.taobao.arthas.core.command.klass100.ClassLoaderCommand;
|
||||
import com.taobao.arthas.core.command.klass100.DumpClassCommand;
|
||||
import com.taobao.arthas.core.command.klass100.GetStaticCommand;
|
||||
import com.taobao.arthas.core.command.klass100.JadCommand;
|
||||
import com.taobao.arthas.core.command.klass100.OgnlCommand;
|
||||
import com.taobao.arthas.core.command.klass100.RedefineCommand;
|
||||
import com.taobao.arthas.core.command.klass100.SearchClassCommand;
|
||||
import com.taobao.arthas.core.command.klass100.SearchMethodCommand;
|
||||
@@ -66,6 +67,7 @@ public class BuiltinCommandPack implements CommandResolver {
|
||||
commands.add(Command.create(TimeTunnelCommand.class));
|
||||
commands.add(Command.create(JvmCommand.class));
|
||||
// commands.add(Command.create(GroovyScriptCommand.class));
|
||||
commands.add(Command.create(OgnlCommand.class));
|
||||
commands.add(Command.create(DashboardCommand.class));
|
||||
commands.add(Command.create(DumpClassCommand.class));
|
||||
commands.add(Command.create(JulyCommand.class));
|
||||
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
package com.taobao.arthas.core.command.express;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import ognl.ClassResolver;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author hengyunabc 2018-10-18
|
||||
* @see ognl.DefaultClassResolver
|
||||
*/
|
||||
public class ClassLoaderClassResolver implements ClassResolver {
|
||||
|
||||
private ClassLoader classLoader;
|
||||
|
||||
private Map<String, Class<?>> classes = new ConcurrentHashMap<String, Class<?>>(101);
|
||||
|
||||
public ClassLoaderClassResolver(ClassLoader classLoader) {
|
||||
this.classLoader = classLoader;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> classForName(String className, @SuppressWarnings("rawtypes") Map context)
|
||||
throws ClassNotFoundException {
|
||||
Class<?> result = null;
|
||||
|
||||
if ((result = classes.get(className)) == null) {
|
||||
try {
|
||||
result = classLoader.loadClass(className);
|
||||
} catch (ClassNotFoundException ex) {
|
||||
if (className.indexOf('.') == -1) {
|
||||
result = Class.forName("java.lang." + className);
|
||||
classes.put("java.lang." + className, result);
|
||||
}
|
||||
}
|
||||
classes.put(className, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -23,4 +23,7 @@ public class ExpressFactory {
|
||||
return expressRef.get().reset().bind(object);
|
||||
}
|
||||
|
||||
public static Express unpooledExpress(ClassLoader classloader) {
|
||||
return new OgnlExpress(new ClassLoaderClassResolver(classloader));
|
||||
}
|
||||
}
|
||||
@@ -2,12 +2,15 @@ package com.taobao.arthas.core.command.express;
|
||||
|
||||
import com.taobao.arthas.core.util.LogUtil;
|
||||
import com.taobao.middleware.logger.Logger;
|
||||
|
||||
import ognl.ClassResolver;
|
||||
import ognl.DefaultMemberAccess;
|
||||
import ognl.Ognl;
|
||||
import ognl.OgnlContext;
|
||||
|
||||
/**
|
||||
* @author ralf0131 2017-01-04 14:41.
|
||||
* @author hengyunabc 2018-10-18
|
||||
*/
|
||||
public class OgnlExpress implements Express {
|
||||
|
||||
@@ -17,14 +20,19 @@ public class OgnlExpress implements Express {
|
||||
private final OgnlContext context;
|
||||
|
||||
public OgnlExpress() {
|
||||
this(CustomClassResolver.customClassResolver);
|
||||
}
|
||||
|
||||
public OgnlExpress(ClassResolver classResolver) {
|
||||
context = new OgnlContext();
|
||||
context.setClassResolver(CustomClassResolver.customClassResolver);
|
||||
context.setClassResolver(classResolver);
|
||||
// allow private field access
|
||||
context.setMemberAccess(new DefaultMemberAccess(true));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object get(String express) throws ExpressException {
|
||||
try {
|
||||
context.setMemberAccess(new DefaultMemberAccess(true));
|
||||
return Ognl.getValue(express, context, bindObject);
|
||||
} catch (Exception e) {
|
||||
logger.error(null, "Error during evaluating the expression:", e);
|
||||
|
||||
@@ -73,7 +73,7 @@ public class GetStaticCommand extends AnnotatedCommand {
|
||||
|
||||
@Option(shortName = "c", longName = "classloader")
|
||||
@Description("The hash code of the special class's classLoader")
|
||||
public void setCode(String hashCode) {
|
||||
public void setHashCode(String hashCode) {
|
||||
this.hashCode = hashCode;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
package com.taobao.arthas.core.command.klass100;
|
||||
|
||||
import java.lang.instrument.Instrumentation;
|
||||
|
||||
import com.taobao.arthas.core.command.Constants;
|
||||
import com.taobao.arthas.core.command.express.Express;
|
||||
import com.taobao.arthas.core.command.express.ExpressException;
|
||||
import com.taobao.arthas.core.command.express.ExpressFactory;
|
||||
import com.taobao.arthas.core.shell.command.AnnotatedCommand;
|
||||
import com.taobao.arthas.core.shell.command.CommandProcess;
|
||||
import com.taobao.arthas.core.util.LogUtil;
|
||||
import com.taobao.arthas.core.util.StringUtils;
|
||||
import com.taobao.arthas.core.view.ObjectView;
|
||||
import com.taobao.middleware.cli.annotations.Argument;
|
||||
import com.taobao.middleware.cli.annotations.Description;
|
||||
import com.taobao.middleware.cli.annotations.Name;
|
||||
import com.taobao.middleware.cli.annotations.Option;
|
||||
import com.taobao.middleware.cli.annotations.Summary;
|
||||
import com.taobao.middleware.logger.Logger;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author hengyunabc 2018-10-18
|
||||
*
|
||||
*/
|
||||
@Name("ognl")
|
||||
@Summary("Execute ognl expression.")
|
||||
@Description(Constants.EXAMPLE
|
||||
+ " ognl '@java.lang.System@out.println(\"hello\")' \n"
|
||||
+ " ognl -x 2 '@Singleton@getInstance() \n"
|
||||
+ " ognl '@Demo@staticFiled' \n"
|
||||
+ " ognl '#value1=@System@getProperty(\"java.home\"), #value2=@System@getProperty(\"java.runtime.name\"), {#value1, #value2}'\n"
|
||||
+ " ognl -c 5d113a51 '@com.taobao.arthas.core.GlobalOptions@isDump' \n"
|
||||
+ Constants.WIKI + Constants.WIKI_HOME + "ognl\n"
|
||||
+ " https://commons.apache.org/proper/commons-ognl/language-guide.html")
|
||||
public class OgnlCommand extends AnnotatedCommand {
|
||||
private static final Logger logger = LogUtil.getArthasLogger();
|
||||
|
||||
private String express;
|
||||
|
||||
private String hashCode;
|
||||
private int expand = 1;
|
||||
|
||||
@Argument(argName = "express", index = 0, required = true)
|
||||
@Description("The ognl expression.")
|
||||
public void setExpress(String express) {
|
||||
this.express = express;
|
||||
}
|
||||
|
||||
@Option(shortName = "c", longName = "classLoader")
|
||||
@Description("The hash code of the special class's classLoader, default classLoader is SystemClassLoader.")
|
||||
public void setHashCode(String hashCode) {
|
||||
this.hashCode = hashCode;
|
||||
}
|
||||
|
||||
@Option(shortName = "x", longName = "expand")
|
||||
@Description("Expand level of object (1 by default).")
|
||||
public void setExpand(Integer expand) {
|
||||
this.expand = expand;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void process(CommandProcess process) {
|
||||
int exitCode = 0;
|
||||
try {
|
||||
Instrumentation inst = process.session().getInstrumentation();
|
||||
ClassLoader classLoader = null;
|
||||
if (hashCode == null) {
|
||||
classLoader = ClassLoader.getSystemClassLoader();
|
||||
} else {
|
||||
classLoader = findClassLoader(inst, hashCode);
|
||||
}
|
||||
|
||||
if (classLoader == null) {
|
||||
process.write("Can not find classloader with hashCode: " + hashCode + ".\n");
|
||||
exitCode = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
Express unpooledExpress = ExpressFactory.unpooledExpress(classLoader);
|
||||
try {
|
||||
Object value = unpooledExpress.get(express);
|
||||
String result = StringUtils.objectToString(expand >= 0 ? new ObjectView(value, expand).draw() : value);
|
||||
process.write(result + "\n");
|
||||
} catch (ExpressException e) {
|
||||
logger.warn("ognl: failed execute express: " + express, e);
|
||||
process.write("Failed to get static, exception message: " + e.getMessage()
|
||||
+ ", please check $HOME/logs/arthas/arthas.log for more details. \n");
|
||||
exitCode = -1;
|
||||
}
|
||||
} finally {
|
||||
process.end(exitCode);
|
||||
}
|
||||
}
|
||||
|
||||
private static ClassLoader findClassLoader(Instrumentation inst, String hashCode) {
|
||||
for (Class<?> clazz : inst.getAllLoadedClasses()) {
|
||||
ClassLoader classLoader = clazz.getClassLoader();
|
||||
if (classLoader != null && hashCode.equals(Integer.toHexString(classLoader.hashCode()))) {
|
||||
return classLoader;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user