jad command support print line numbers. #1 #1695

pull/2037/head
hengyunabc 4 years ago
parent b1b1eb9b9a
commit dc507df175

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

Loading…
Cancel
Save