- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我目前正在构建一个 Java 反编译器。
为了辅助模式识别,我正在通过ANTLR构建一个简单的语法,并使用ANTLRWorks解释器进行调试。
以下是目前为止的初步语法。沿着这条路走下去,我假设我能够将某些 JVM 字节码简化为下面的语法可以检测到的表达式。
您认为这种方法存在哪些问题?格林威治标准时间 6 月 29 日 2:36 更新了 Ira 评论的语法 1
grammar JVM;
options {k=3;}
WS : (' '|'\r'|'\n'|'\t')+ {$channel=HIDDEN;}
;
INT : ('0'..'9')+ ;
UINT : ('_' INT)?;
IFEQ : 'ifeq';
IFGE : 'ifge';
IFGT : 'ifgt';
IFLE : 'ifle';
IFLT : 'iflt';
IFNE : 'ifne';
IFACMP_CONDTYPE : 'if_acmp' ('eq'|'ne'|'lt'|'ge'|'gt'|'le');
// THIS : 'aload_0';
LDC : 'ldc2_w'|'ldc_w'|'ldc';
LOADREFERENCE
// : THIS
: 'aload' UINT;
// | 'aload_2'
// | 'aload_3';
DLOAD : 'dload' UINT;
LOADINT : 'iload_0'
| 'iload_1'
| 'iload_2'
| 'iload_3'
;
DCONST : 'dconst' UINT;
ICONST : 'iconst' UINT;
goal : jvmStatement2+ ;
//fragment
//jvmStatement1
// : returnStatement
// | newArrayStatement
// | storeStatement
// | assignmentStatement
// | assertStatement
// | invokeStatement
// | ifStatement
// | gotoStatement
// ;
fragment // to test assert
jvmStatement2
: returnStatement // 2
| newArrayStatement // 3
| storeStatement // 4
| invokeStatement // 5
| assignmentStatement // 6
| assertStatement // 7
| ifStatement // 8
| gotoStatement
;
fragment
setAssertionStatus
: ifStatement pushIntegerConstant
gotoStatement pushIntegerConstant setStaticFieldInClass;
fragment
fetchFieldFromObject
: LOADREFERENCE 'getfield' INT;
fragment
loadDoubleFromLocalVariable
: DLOAD;
fragment
loadFloatFromLocalVariable
: 'fload' UINT;
fragment
loadIntFromLocalVariable
: LOADINT;
fragment
loadLongFromLocalVariable
: 'lload' UINT;
fragment
loadReferenceFromLocalVariable
: 'aload' UINT;
fragment
loadReferenceFromArray
: 'aaload';
fragment
storeReference
: storeIntoByteOrBooleanArray;
fragment
storeReferenceIntoLocalVariable
: 'astore' UINT;
fragment
storeDoubleIntoLocalVariable
: 'dstore' INT;
fragment
storeFloatIntoLocalVariable
: 'fstore' UINT;
fragment
storeIntIntoLocalVariable
: 'istore' (INT|UINT);
fragment
storeLongIntoLocalVariable
: 'lstore' UINT;
fragment
storeIntoByteOrBooleanArray
: 'bastore';
fragment
storeIntoReferenceArray
: 'aastore';
fragment
pushNull: 'aconst_null';
fragment
pushByte: 'bipush' INT;
fragment
pushIntegerConstant
: ICONST;
fragment
pushDoubleConstant
: DCONST;
fragment
pushLongConstant
: 'lconst' UINT;
fragment
pushFloatConstant
: 'fconst' UINT;
fragment
pushItemFromRuntimeConstantPool
: LDC INT;
fragment invokeStatementArgument: constantExpr
| createAnonymousClass;
fragment createAnonymousClass
: createNewObject dup thisInstance;
fragment invokeStatementArguments: invokeStatementArgument*;
fragment invokeStatement: getStaticField? invokeStatementArguments invokeMethod;
fragment
invokeMethod
: invokeInstanceMethod
| invokeVirtualMethod
| invokeStaticMethod
;
fragment
invokeInstanceMethod
: 'invokespecial' INT;
fragment
invokeVirtualMethod
: 'invokevirtual' INT;
fragment
invokeStaticMethod
: 'invokestatic' INT;
fragment
newArrayStatement
: 'newarray' simpleType;
fragment
setFieldInObject
: 'putfield' INT;
fragment setStaticFieldInClass
: 'putstatic' INT;
fragment
simpleType
: ('boolean'|'byte'|'char'|'double'|'float'|'int'|'long'|'short');
fragment
returnVoid
: 'return';
fragment
returnSimpleType
: returnReference
| returnDouble
| returnFloat
| returnInteger
| returnLong;
fragment
returnReference
: 'areturn';
fragment
returnDouble
: 'dreturn';
fragment returnFloat
: 'freturn';
fragment returnInteger
: 'ireturn';
fragment returnLong
: 'lreturn';
fragment
returnStatement
: returnVoid
| constantExpr returnSimpleType;
fragment
dupX1
: 'dup_x1';
fragment
dup
: 'dup';
fragment
storeStatement
: storeReferenceIntoLocalVariable
| storeIntIntoLocalVariable
| setStaticFieldInClass
| storeIntoReferenceArray
| setFieldInObject;
fragment
convertDouble
: convertDoubleToFloat | convertDoubleToInt | convertDoubleToLong;
fragment
convertDoubleToFloat
: 'd2f';
fragment
convertDoubleToInt
: 'd2i';
fragment
convertDoubleToLong
: 'd2l';
fragment
convertFloat
: convertFloatToDouble|convertFloatToInt|convertFloatToLong;
fragment
convertFloatToDouble
: 'f2d';
fragment
convertFloatToInt
: 'f2i';
fragment
convertFloatToLong
: 'f2l';
fragment
convertInt
: convertIntToByte
|convertIntToChar
|convertIntToDouble
|convertIntToFloat
|convertIntToLong
|convertIntToShort;
fragment
convertIntToByte
: 'i2b';
fragment
convertIntToChar
: 'i2c';
fragment
convertIntToDouble
: 'i2d';
fragment
convertIntToFloat
: 'i2f';
fragment
convertIntToLong
: 'i2l';
fragment
convertIntToShort
: 'i2s';
fragment
branchComparison
:branchIfReferenceComparison
|branchIfIntComparison
|branchIfIntComparisonWithZero
|branchIfReferenceNotNull
|branchIfReferenceNull;
fragment
branchIfReferenceComparison
: 'if_acmp' condType;
fragment
branchIfIntComparison
: 'if_icmp' condType INT;
fragment
branchIfIntComparisonWithZero
: (IFEQ|IFGE|IFGT|IFLE|IFLT|IFNE) INT;
fragment
gotoStatement
: 'goto' INT;
fragment
ifStatementCompare
: (IFEQ INT)
| (IFNE INT);
fragment
ifStatement
: booleanExpression ifStatementCompare;
fragment
ifType : 'ifeq'
|'ifne'
|'iflt'
|'ifge'
|'ifgt'
|'ifle';
fragment
branchIfReferenceNotNull
: 'ifnonnull' ;
fragment
branchIfReferenceNull
: 'ifnull';
fragment
condType: 'eq'
|'ne'
|'lt'
|'ge'
|'gt'
|'le';
fragment
checkCast
: 'checkcast' INT;
fragment
createNewArrayOfReference
: constantExpr 'anewarray' INT;
fragment
createNewObject
: 'new' INT;
fragment
assignmentStatement
// : pushItemFromRuntimeConstantPool storeStatement
: (constantExpr)+ storeStatement
| invokeInheritedConstructor
| expressionStatement
// | setAssertionStatus
;
fragment
invokeInheritedConstructor
: loadReferenceFromLocalVariable invokeInstanceMethod;
fragment
throwExceptionOrError
: 'athrow';
fragment
getStaticField
: 'getstatic' INT;
fragment
newInstance
: 'new' INT;
fragment // this needs to be extended to recognize more patterns
booleanExpression
: integerComparison
| loadIntFromLocalVariable
| invokeMethod;
fragment
integerComparison
: loadIntFromLocalVariable loadIntFromLocalVariable branchIfIntComparison;
fragment assertIfAssertEnabled: getStaticField branchIfIntComparisonWithZero;
fragment assertCondition:booleanExpression branchIfIntComparisonWithZero;
fragment assertThrow:createNewObject dup assertMessage throwExceptionOrError;
fragment assertMessage:pushItemFromRuntimeConstantPool invokeMethod;
fragment assertStatement:assertIfAssertEnabled assertCondition assertThrow;
fragment
stringPlusNumber
:pushItemFromRuntimeConstantPool invokeMethod
loadReferenceFromLocalVariable invokeMethod invokeMethod invokeMethod;
fragment expressionStatement: statementExpression;
fragment
statementExpression
: preIncrementExpression
| preDecrementExpression
// | postIncrementExpression
// | postDecrementExpression
| newByteArray
| ternaryExpression
| createAndStoreObject // assignment expression
| createNewArrayStatement
| fetchFieldFromObject
;
fragment
createNewArrayStatement // with elements
: createNewArrayOfReference createNewArrayInitElement+;
createNewArrayInitElement
: (dup constantExpr getStaticField storeStatement);
fragment
createAndStoreObject
: createNewObject dup invokeStatement storeStatement;
fragment ternaryExpression // doesn't cover all situations yet
: loadIntFromLocalVariable ifStatementCompare loadIntFromLocalVariable gotoStatement
loadIntFromLocalVariable storeStatement;
fragment preIncrementExpression: preIncrementInteger;
fragment preDecrementExpression: preDecrementFloat|preDecrementLong|preDecrementDouble;
fragment doubleExpression: pushDoubleConstant;
fragment integerExpression: pushIntegerConstant;
fragment longExpression: pushLongConstant;
fragment floatExpression: pushFloatConstant;
fragment preIncrementInteger: loadReferenceFromLocalVariable dup fetchFieldFromObject integerExpression
iAdd dupX1? setFieldInObject;
fragment preDecrementDouble: loadDoubleFromLocalVariable doubleExpression dSub storeDoubleIntoLocalVariable;
fragment preDecrementLong: loadLongFromLocalVariable longExpression lSub storeLongIntoLocalVariable;
fragment preDecrementFloat: loadFloatFromLocalVariable floatExpression fSub storeFloatIntoLocalVariable;
fragment newByteArray: newByteArrayWithNull|newByteArrayWithData;
// byte[] b = {'c', 'h', 'u', 'a'};
fragment newByteArrayWithData: constantExpr newArrayStatement byteArrayElements;
fragment byteArrayElements: constantExpr constantExpr storeIntoByteOrBooleanArray;
fragment constantExpr:
//loadReferenceFromLocalVariable
LOADREFERENCE
|loadDoubleFromLocalVariable
|loadFloatFromLocalVariable
|loadIntFromLocalVariable
|loadLongFromLocalVariable
|pushByte
|pushDoubleConstant
|pushFloatConstant
|pushIntegerConstant
|pushItemFromRuntimeConstantPool
|pushLongConstant
|pushNull
|fetchFieldFromObject
;
// byte[] c = null;
// String s = null;
fragment newByteArrayWithNull: pushNull (checkCast)? storeReference;
fragment thisInstance: LOADREFERENCE invokeMethod;
fragment ternaryOperator
: ifStatementCompare pushIntegerConstant gotoStatement pushIntegerConstant setStaticFieldInClass;
fragment floatMultiply
: constantExpr constantExpr dMul;
fragment iAdd: 'iadd';
fragment dSub: 'dsub';
fragment fSub: 'fsub';
fragment lSub: 'lsub';
fragment lAdd: 'ladd';
fragment dMul: 'dmul';
比如现在的文法(上面的进一步演化)可以转
getstatic 25
ifne 25
iload_1
iload_2
if_icmpgt 25
new 25
dup
invokespecial 44
athrow
return
进入
最佳答案
如果您只想识别各个 JVM 指令,那么语法可能就可以了。您可能会花时间摆弄语法以获得正确的细节。这可能是简单的矫枉过正。字节操作码驱动的有限状态自动机 (FSA) 实现为巨大的 case 语句可能更容易;毕竟,JVM 指令应该易于解码,以便半快速解释器可以执行这些指令。
根据模糊的记忆,类文件中还有其他部分(表格,例如文字)。您可能也可以通过解析器识别它们,但也可能矫枉过正。
你有第二个问题,识别后收集指令/表信息;解析器生成器往往希望帮助您构建某种 AST。这些说明不是 AST;它们至少是一个线性链,如果您包括跳跃目标,它们会形成一个包含对表格的引用的图表。所以我怀疑您最终会努力获得语义操作,以按照您想要的方式收集数据。
它是您可能想要捕获的图表。就图具有某种层次结构(从结构化编程语言派生而来)而言,您可能想要发现该层次结构。解析器方法在这里没有任何贡献。
关于java - 通过文法构建Java Decompiler会出现什么问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11117130/
我正在编写一个具有以下签名的 Java 方法。 void Logger(Method method, Object[] args); 如果一个方法(例如 ABC() )调用此方法 Logger,它应该
我是 Java 新手。 我的问题是我的 Java 程序找不到我试图用作的图像文件一个 JButton。 (目前这段代码什么也没做,因为我只是得到了想要的外观第一的)。这是我的主课 代码: packag
好的,今天我在接受采访,我已经编写 Java 代码多年了。采访中说“Java 垃圾收集是一个棘手的问题,我有几个 friend 一直在努力弄清楚。你在这方面做得怎么样?”。她是想骗我吗?还是我的一生都
我的 friend 给了我一个谜语让我解开。它是这样的: There are 100 people. Each one of them, in his turn, does the following
如果我将使用 Java 5 代码的应用程序编译成字节码,生成的 .class 文件是否能够在 Java 1.4 下运行? 如果后者可以工作并且我正在尝试在我的 Java 1.4 应用程序中使用 Jav
有关于why Java doesn't support unsigned types的问题以及一些关于处理无符号类型的问题。我做了一些搜索,似乎 Scala 也不支持无符号数据类型。限制是Java和S
我只是想知道在一个 java 版本中生成的字节码是否可以在其他 java 版本上运行 最佳答案 通常,字节码无需修改即可在 较新 版本的 Java 上运行。它不会在旧版本上运行,除非您使用特殊参数 (
我有一个关于在命令提示符下执行 java 程序的基本问题。 在某些机器上我们需要指定 -cp 。 (类路径)同时执行java程序 (test为java文件名与.class文件存在于同一目录下) jav
我已经阅读 StackOverflow 有一段时间了,现在我才鼓起勇气提出问题。我今年 20 岁,目前在我的家乡(罗马尼亚克卢日-纳波卡)就读 IT 大学。足以介绍:D。 基本上,我有一家提供簿记应用
我有 public JSONObject parseXML(String xml) { JSONObject jsonObject = XML.toJSONObject(xml); r
我已经在 Java 中实现了带有动态类型的简单解释语言。不幸的是我遇到了以下问题。测试时如下代码: def main() { def ks = Map[[1, 2]].keySet()
一直提示输入 1 到 10 的数字 - 结果应将 st、rd、th 和 nd 添加到数字中。编写一个程序,提示用户输入 1 到 10 之间的任意整数,然后以序数形式显示该整数并附加后缀。 public
我有这个 DownloadFile.java 并按预期下载该文件: import java.io.*; import java.net.URL; public class DownloadFile {
我想在 GUI 上添加延迟。我放置了 2 个 for 循环,然后重新绘制了一个标签,但这 2 个 for 循环一个接一个地执行,并且标签被重新绘制到最后一个。 我能做什么? for(int i=0;
我正在对对象 Student 的列表项进行一些测试,但是我更喜欢在 java 类对象中创建硬编码列表,然后从那里提取数据,而不是连接到数据库并在结果集中选择记录。然而,自从我这样做以来已经很长时间了,
我知道对象创建分为三个部分: 声明 实例化 初始化 classA{} classB extends classA{} classA obj = new classB(1,1); 实例化 它必须使用
我有兴趣使用 GPRS 构建车辆跟踪系统。但是,我有一些问题要问以前做过此操作的人: GPRS 是最好的技术吗?人们意识到任何问题吗? 我计划使用 Java/Java EE - 有更好的技术吗? 如果
我可以通过递归方法反转数组,例如:数组={1,2,3,4,5} 数组结果={5,4,3,2,1}但我的结果是相同的数组,我不知道为什么,请帮助我。 public class Recursion { p
有这样的标准方式吗? 包括 Java源代码-测试代码- Ant 或 Maven联合单元持续集成(可能是巡航控制)ClearCase 版本控制工具部署到应用服务器 最后我希望有一个自动构建和集成环境。
我什至不知道这是否可能,我非常怀疑它是否可能,但如果可以,您能告诉我怎么做吗?我只是想知道如何从打印机打印一些文本。 有什么想法吗? 最佳答案 这里有更简单的事情。 import javax.swin
我是一名优秀的程序员,十分优秀!