add ognl command. #240

pull/539/head
hengyunabc 6 years ago
parent bffd6fff8d
commit 82dc3b1922

@ -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));

@ -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;
}
}
Loading…
Cancel
Save