mirror of
https://gitee.com/arthas/arthas.git
synced 2024-12-05 05:37:37 +08:00
update bytekit Decompiler.java
This commit is contained in:
parent
e6926f91f7
commit
4f15c1072f
@ -5,33 +5,16 @@ import java.io.IOException;
|
|||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.io.StringWriter;
|
import java.io.StringWriter;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.FileUtils;
|
||||||
import org.apache.commons.lang3.RandomStringUtils;
|
import org.apache.commons.lang3.RandomStringUtils;
|
||||||
import org.benf.cfr.reader.api.ClassFileSource;
|
import org.benf.cfr.reader.api.CfrDriver;
|
||||||
import org.benf.cfr.reader.bytecode.analysis.parse.utils.Pair;
|
import org.benf.cfr.reader.api.OutputSinkFactory;
|
||||||
import org.benf.cfr.reader.entities.ClassFile;
|
|
||||||
import org.benf.cfr.reader.entities.Method;
|
|
||||||
import org.benf.cfr.reader.relationship.MemberNameResolver;
|
|
||||||
import org.benf.cfr.reader.state.ClassFileSourceImpl;
|
|
||||||
import org.benf.cfr.reader.state.DCCommonState;
|
|
||||||
import org.benf.cfr.reader.state.TypeUsageCollector;
|
|
||||||
import org.benf.cfr.reader.state.TypeUsageInformation;
|
|
||||||
import org.benf.cfr.reader.util.AnalysisType;
|
|
||||||
import org.benf.cfr.reader.util.CannotLoadClassException;
|
|
||||||
import org.benf.cfr.reader.util.ConfusedCFRException;
|
|
||||||
import org.benf.cfr.reader.util.ListFactory;
|
|
||||||
import org.benf.cfr.reader.util.getopt.GetOptParser;
|
|
||||||
import org.benf.cfr.reader.util.getopt.Options;
|
|
||||||
import org.benf.cfr.reader.util.getopt.OptionsImpl;
|
|
||||||
import org.benf.cfr.reader.util.output.Dumper;
|
|
||||||
import org.benf.cfr.reader.util.output.DumperFactory;
|
|
||||||
import org.benf.cfr.reader.util.output.DumperFactoryImpl;
|
|
||||||
import org.benf.cfr.reader.util.output.IllegalIdentifierDump;
|
|
||||||
import org.benf.cfr.reader.util.output.StreamDumper;
|
|
||||||
import org.benf.cfr.reader.util.output.ToStringDumper;
|
|
||||||
import com.alibaba.arthas.deps.org.objectweb.asm.tree.AbstractInsnNode;
|
import com.alibaba.arthas.deps.org.objectweb.asm.tree.AbstractInsnNode;
|
||||||
import com.alibaba.arthas.deps.org.objectweb.asm.tree.ClassNode;
|
import com.alibaba.arthas.deps.org.objectweb.asm.tree.ClassNode;
|
||||||
import com.alibaba.arthas.deps.org.objectweb.asm.tree.InsnList;
|
import com.alibaba.arthas.deps.org.objectweb.asm.tree.InsnList;
|
||||||
@ -41,6 +24,11 @@ import com.alibaba.arthas.deps.org.objectweb.asm.util.Textifier;
|
|||||||
import com.alibaba.arthas.deps.org.objectweb.asm.util.TraceClassVisitor;
|
import com.alibaba.arthas.deps.org.objectweb.asm.util.TraceClassVisitor;
|
||||||
import com.alibaba.arthas.deps.org.objectweb.asm.util.TraceMethodVisitor;
|
import com.alibaba.arthas.deps.org.objectweb.asm.util.TraceMethodVisitor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO com.taobao.arthas.core.util.Decompiler
|
||||||
|
* @author hengyunabc
|
||||||
|
*
|
||||||
|
*/
|
||||||
public class Decompiler {
|
public class Decompiler {
|
||||||
|
|
||||||
public static String decompile(byte[] bytecode) throws IOException {
|
public static String decompile(byte[] bytecode) throws IOException {
|
||||||
@ -113,159 +101,52 @@ public class Decompiler {
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see org.benf.cfr.reader.Main#main(String[])
|
|
||||||
* @param classFilePath
|
* @param classFilePath
|
||||||
* @param methodName
|
* @param methodName
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public static String decompile(String classFilePath, String methodName) {
|
public static String decompile(String classFilePath, String methodName) {
|
||||||
StringBuilder result = new StringBuilder(8192);
|
final StringBuilder result = new StringBuilder(8192);
|
||||||
|
|
||||||
List<String> argList = new ArrayList<String>();
|
OutputSinkFactory mySink = new OutputSinkFactory() {
|
||||||
argList.add(classFilePath);
|
@Override
|
||||||
|
public List<SinkClass> getSupportedSinks(SinkType sinkType, Collection<SinkClass> collection) {
|
||||||
|
return Arrays.asList(SinkClass.STRING, SinkClass.DECOMPILED, SinkClass.DECOMPILED_MULTIVER,
|
||||||
|
SinkClass.EXCEPTION_MESSAGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> Sink<T> getSink(final SinkType sinkType, SinkClass sinkClass) {
|
||||||
|
return new Sink<T>() {
|
||||||
|
@Override
|
||||||
|
public void write(T sinkable) {
|
||||||
|
// skip message like: Analysing type demo.MathGame
|
||||||
|
if (sinkType == SinkType.PROGRESS) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
result.append(sinkable);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
HashMap<String, String> options = new HashMap<String, String>();
|
||||||
|
/**
|
||||||
|
* @see org.benf.cfr.reader.util.MiscConstants.Version.getVersion() Currently,
|
||||||
|
* the cfr version is wrong. so disable show cfr version.
|
||||||
|
*/
|
||||||
|
options.put("showversion", "false");
|
||||||
if (methodName != null) {
|
if (methodName != null) {
|
||||||
argList.add("--methodname");
|
options.put("methodname", methodName);
|
||||||
argList.add(methodName);
|
|
||||||
}
|
|
||||||
String args[] = argList.toArray(new String[0]);
|
|
||||||
|
|
||||||
GetOptParser getOptParser = new GetOptParser();
|
|
||||||
|
|
||||||
Options options = null;
|
|
||||||
List<String> files = null;
|
|
||||||
try {
|
|
||||||
Pair processedArgs = getOptParser.parse(args, OptionsImpl.getFactory());
|
|
||||||
files = (List) processedArgs.getFirst();
|
|
||||||
options = (Options) processedArgs.getSecond();
|
|
||||||
} catch (Exception e) {
|
|
||||||
getOptParser.showHelp(OptionsImpl.getFactory(), e);
|
|
||||||
System.exit(1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((options.optionIsSet(OptionsImpl.HELP)) || (files.isEmpty())) {
|
CfrDriver driver = new CfrDriver.Builder().withOptions(options).withOutputSink(mySink).build();
|
||||||
getOptParser.showOptionHelp(OptionsImpl.getFactory(), options, OptionsImpl.HELP);
|
List<String> toAnalyse = new ArrayList<String>();
|
||||||
return "";
|
toAnalyse.add(classFilePath);
|
||||||
}
|
driver.analyse(toAnalyse);
|
||||||
|
|
||||||
ClassFileSourceImpl classFileSource = new ClassFileSourceImpl(options);
|
|
||||||
|
|
||||||
boolean skipInnerClass = (files.size() > 1)
|
|
||||||
&& (((Boolean) options.getOption(OptionsImpl.SKIP_BATCH_INNER_CLASSES)).booleanValue());
|
|
||||||
|
|
||||||
Collections.sort(files);
|
|
||||||
|
|
||||||
for (String path : files) {
|
|
||||||
classFileSource.clearConfiguration();
|
|
||||||
DCCommonState dcCommonState = new DCCommonState(options, classFileSource);
|
|
||||||
DumperFactory dumperFactory = new DumperFactoryImpl(options);
|
|
||||||
|
|
||||||
path = classFileSource.adjustInputPath(path);
|
|
||||||
|
|
||||||
AnalysisType type = (AnalysisType) options.getOption(OptionsImpl.ANALYSE_AS);
|
|
||||||
if (type == null)
|
|
||||||
type = dcCommonState.detectClsJar(path);
|
|
||||||
|
|
||||||
if (type == AnalysisType.JAR) {
|
|
||||||
// doJar(dcCommonState, path, dumperFactory);
|
|
||||||
}
|
|
||||||
if (type == AnalysisType.CLASS)
|
|
||||||
result.append(doClass(dcCommonState, path, skipInnerClass, dumperFactory));
|
|
||||||
}
|
|
||||||
return result.toString();
|
return result.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String doClass(DCCommonState dcCommonState, String path, boolean skipInnerClass,
|
|
||||||
DumperFactory dumperFactory) {
|
|
||||||
StringBuilder result = new StringBuilder(8192);
|
|
||||||
Options options = dcCommonState.getOptions();
|
|
||||||
IllegalIdentifierDump illegalIdentifierDump = IllegalIdentifierDump.Factory.get(options);
|
|
||||||
Dumper d = new ToStringDumper();
|
|
||||||
try {
|
|
||||||
ClassFile c = dcCommonState.getClassFileMaybePath(path);
|
|
||||||
if ((skipInnerClass) && (c.isInnerClass()))
|
|
||||||
return "";
|
|
||||||
dcCommonState.configureWith(c);
|
|
||||||
dumperFactory.getProgressDumper().analysingType(c.getClassType());
|
|
||||||
try {
|
|
||||||
c = dcCommonState.getClassFile(c.getClassType());
|
|
||||||
} catch (CannotLoadClassException e) {
|
|
||||||
}
|
|
||||||
if (((Boolean) options.getOption(OptionsImpl.DECOMPILE_INNER_CLASSES)).booleanValue()) {
|
|
||||||
c.loadInnerClasses(dcCommonState);
|
|
||||||
}
|
|
||||||
if (((Boolean) options.getOption(OptionsImpl.RENAME_DUP_MEMBERS)).booleanValue()) {
|
|
||||||
MemberNameResolver.resolveNames(dcCommonState,
|
|
||||||
ListFactory.newList(dcCommonState.getClassCache().getLoadedTypes()));
|
|
||||||
}
|
|
||||||
|
|
||||||
c.analyseTop(dcCommonState);
|
|
||||||
|
|
||||||
TypeUsageCollector collectingDumper = new TypeUsageCollector(c);
|
|
||||||
c.collectTypeUsages(collectingDumper);
|
|
||||||
|
|
||||||
d = new StringDumper(collectingDumper.getTypeUsageInformation(), options, illegalIdentifierDump);
|
|
||||||
|
|
||||||
// d = dumperFactory.getNewTopLevelDumper(c.getClassType(), summaryDumper,
|
|
||||||
// collectingDumper.getTypeUsageInformation(), illegalIdentifierDump);
|
|
||||||
|
|
||||||
String methname = (String) options.getOption(OptionsImpl.METHODNAME);
|
|
||||||
if (methname == null)
|
|
||||||
c.dump(d);
|
|
||||||
else {
|
|
||||||
try {
|
|
||||||
for (Method method : c.getMethodByName(methname))
|
|
||||||
method.dump(d, true);
|
|
||||||
} catch (NoSuchMethodException e) {
|
|
||||||
throw new IllegalArgumentException("No such method '" + methname + "'.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
d.print("");
|
|
||||||
result.append(d.toString());
|
|
||||||
} catch (ConfusedCFRException e) {
|
|
||||||
result.append(e.toString()).append("\n");
|
|
||||||
for (Object x : e.getStackTrace())
|
|
||||||
result.append(x).append("\n");
|
|
||||||
} catch (CannotLoadClassException e) {
|
|
||||||
result.append("Can't load the class specified:").append("\n");
|
|
||||||
result.append(e.toString()).append("\n");
|
|
||||||
} catch (RuntimeException e) {
|
|
||||||
result.append(e.toString()).append("\n");
|
|
||||||
for (Object x : e.getStackTrace())
|
|
||||||
result.append(x).append("\n");
|
|
||||||
} finally {
|
|
||||||
if (d != null)
|
|
||||||
d.close();
|
|
||||||
}
|
|
||||||
return result.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class StringDumper extends StreamDumper {
|
|
||||||
private StringWriter sw = new StringWriter();
|
|
||||||
|
|
||||||
public StringDumper(TypeUsageInformation typeUsageInformation, Options options,
|
|
||||||
IllegalIdentifierDump illegalIdentifierDump) {
|
|
||||||
super(typeUsageInformation, options, illegalIdentifierDump);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addSummaryError(Method paramMethod, String paramString) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void close() {
|
|
||||||
try {
|
|
||||||
sw.close();
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void write(String source) {
|
|
||||||
sw.write(source);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toString() {
|
|
||||||
return sw.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user