mirror of
https://github.com/alibaba/arthas.git
synced 2024-04-21 10:21:39 +00:00
@@ -21,6 +21,7 @@ import com.taobao.arthas.core.util.InstrumentationUtils;
|
||||
import com.taobao.arthas.core.util.SearchUtils;
|
||||
import com.taobao.arthas.core.util.affect.RowAffect;
|
||||
import com.taobao.middleware.cli.annotations.Argument;
|
||||
import com.taobao.middleware.cli.annotations.DefaultValue;
|
||||
import com.taobao.middleware.cli.annotations.Description;
|
||||
import com.taobao.middleware.cli.annotations.Name;
|
||||
import com.taobao.middleware.cli.annotations.Option;
|
||||
@@ -58,6 +59,7 @@ public class JadCommand extends AnnotatedCommand {
|
||||
private String classLoaderClass;
|
||||
private boolean isRegEx = false;
|
||||
private boolean hideUnicode = false;
|
||||
private boolean lineNumber;
|
||||
|
||||
/**
|
||||
* jad output source code only
|
||||
@@ -107,6 +109,13 @@ public class JadCommand extends AnnotatedCommand {
|
||||
this.sourceOnly = sourceOnly;
|
||||
}
|
||||
|
||||
@Option(longName = "lineNumber")
|
||||
@DefaultValue("true")
|
||||
@Description("Output source code contins line number, default value true")
|
||||
public void setLineNumber(boolean lineNumber) {
|
||||
this.lineNumber = lineNumber;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void process(CommandProcess process) {
|
||||
RowAffect affect = new RowAffect();
|
||||
@@ -168,7 +177,7 @@ public class JadCommand extends AnnotatedCommand {
|
||||
Map<Class<?>, File> classFiles = transformer.getDumpResult();
|
||||
File classFile = classFiles.get(c);
|
||||
|
||||
String source = Decompiler.decompile(classFile.getAbsolutePath(), methodName, hideUnicode);
|
||||
String source = Decompiler.decompile(classFile.getAbsolutePath(), methodName, hideUnicode, lineNumber);
|
||||
if (source != null) {
|
||||
source = pattern.matcher(source).replaceAll("");
|
||||
} else {
|
||||
|
||||
@@ -5,9 +5,13 @@ import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.NavigableMap;
|
||||
|
||||
import org.benf.cfr.reader.api.CfrDriver;
|
||||
import org.benf.cfr.reader.api.OutputSinkFactory;
|
||||
import org.benf.cfr.reader.api.SinkReturns.LineNumberMapping;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -20,24 +24,31 @@ public class Decompiler {
|
||||
return decompile(classFilePath, methodName, false);
|
||||
}
|
||||
|
||||
public static String decompile(String classFilePath, String methodName, boolean hideUnicode) {
|
||||
return decompile(classFilePath, methodName, hideUnicode, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param classFilePath
|
||||
* @param methodName
|
||||
* @param hideUnicode
|
||||
* @return
|
||||
*/
|
||||
public static String decompile(String classFilePath, String methodName, boolean hideUnicode) {
|
||||
final StringBuilder result = new StringBuilder(8192);
|
||||
public static String decompile(String classFilePath, String methodName, boolean hideUnicode,
|
||||
boolean printLineNumber) {
|
||||
final StringBuilder sb = new StringBuilder(8192);
|
||||
|
||||
final Map<Integer, Integer> lineMapping = new HashMap<Integer, Integer>();
|
||||
|
||||
OutputSinkFactory mySink = new OutputSinkFactory() {
|
||||
@Override
|
||||
public List<SinkClass> getSupportedSinks(SinkType sinkType, Collection<SinkClass> collection) {
|
||||
return Arrays.asList(SinkClass.STRING, SinkClass.DECOMPILED, SinkClass.DECOMPILED_MULTIVER,
|
||||
SinkClass.EXCEPTION_MESSAGE);
|
||||
SinkClass.EXCEPTION_MESSAGE, SinkClass.LINE_NUMBER_MAPPING);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> Sink<T> getSink(final SinkType sinkType, SinkClass sinkClass) {
|
||||
public <T> Sink<T> getSink(final SinkType sinkType, final SinkClass sinkClass) {
|
||||
return new Sink<T>() {
|
||||
@Override
|
||||
public void write(T sinkable) {
|
||||
@@ -45,7 +56,19 @@ public class Decompiler {
|
||||
if (sinkType == SinkType.PROGRESS) {
|
||||
return;
|
||||
}
|
||||
result.append(sinkable);
|
||||
if (sinkType == SinkType.LINENUMBER) {
|
||||
LineNumberMapping mapping = (LineNumberMapping) sinkable;
|
||||
NavigableMap<Integer, Integer> classFileMappings = mapping.getClassFileMappings();
|
||||
NavigableMap<Integer,Integer> mappings = mapping.getMappings();
|
||||
if (classFileMappings != null && mappings != null) {
|
||||
for (Entry<Integer, Integer> entry : mappings.entrySet()) {
|
||||
Integer srcLineNumber = classFileMappings.get(entry.getKey());
|
||||
lineMapping.put(entry.getValue(), srcLineNumber);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
sb.append(sinkable);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -58,6 +81,7 @@ public class Decompiler {
|
||||
*/
|
||||
options.put("showversion", "false");
|
||||
options.put("hideutf", String.valueOf(hideUnicode));
|
||||
options.put("trackbytecodeloc", "true");
|
||||
if (!StringUtils.isBlank(methodName)) {
|
||||
options.put("methodname", methodName);
|
||||
}
|
||||
@@ -67,7 +91,45 @@ public class Decompiler {
|
||||
toAnalyse.add(classFilePath);
|
||||
driver.analyse(toAnalyse);
|
||||
|
||||
return result.toString();
|
||||
String result = sb.toString();
|
||||
if (printLineNumber && !lineMapping.isEmpty()) {
|
||||
result = addLineNumber(result, lineMapping);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static String addLineNumber(String src, Map<Integer, Integer> lineMapping) {
|
||||
int maxLineNumber = 0;
|
||||
for (Integer value : lineMapping.values()) {
|
||||
if (value != null && value > maxLineNumber) {
|
||||
maxLineNumber = value;
|
||||
}
|
||||
}
|
||||
|
||||
String formatStr = "/*%2d*/ ";
|
||||
String emptyStr = " ";
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
String[] lines = src.split("\\R");
|
||||
|
||||
if (maxLineNumber >= 100) {
|
||||
formatStr = "/*%3d*/ ";
|
||||
emptyStr = " ";
|
||||
} else if (maxLineNumber >= 1000) {
|
||||
formatStr = "/*%4d*/ ";
|
||||
emptyStr = " ";
|
||||
}
|
||||
for (int i = 0; i < lines.length; ++i) {
|
||||
Integer srcLineNumber = lineMapping.get(i + 1);
|
||||
if (srcLineNumber != null) {
|
||||
sb.append(String.format(formatStr, srcLineNumber));
|
||||
} else {
|
||||
sb.append(emptyStr);
|
||||
}
|
||||
sb.append(lines[i]).append("\n");
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user