CPython解释器会自动将Python模块编译为.pyc文件.包含字节码的.pyc文件是二进制格式(封送代码?).是否有GUI(或命令行)工具让我查看字节码?
我看到一些java反编译器可以将字节码反编译成可读的java源代码,我想知道来自java(不是其他JVM语言)的所有字节码是否可以再次反编译为java源代码?
更新
对不起,让我更清楚地提出问题.
刚谈谈JVM上的普通Java代码(没有Android,没有字节码增强,没有AOP,没有混淆),我实际上希望字节码可以被反编译.但是我不知道是否有编译成字节码的java代码形式,永远不能被反编译成可读的java源代码.
我的教授最近说过虽然x = x + 1并且x++显然会给出相同的结果,但它们在JVM中的实现方式却有所不同.这是什么意思?编译器不是这样的:嘿,我明白x++我会把它切换到x = x + 1继续吗?
我怀疑在效率方面有什么不同,但如果在这些情况下装配会有所不同,我会感到惊讶......
我正在研究计算StackFrameMap(SFM)中条目的代码.目标是能够生成(SFM)条目,使Java 7字节码验证器满意.遵循TDD方法,我开始为验证者创建伪造的SMF条目以进行投诉; 我会用我正确计算的条目替换它们,看看我是否正确地做了.
问题是:我不能让字节码验证器抱怨.这是一个示例,从原始Java代码开始(此代码不应该做任何有用的事情):
public int stackFrameTest(int x) {
if (x > 0) {
System.out.println("positive x");
}
return -x;
}
Run Code Online (Sandbox Code Playgroud)
这会生成以下字节码(使用SFM):
public int stackFrameTest(int);
flags: ACC_PUBLIC
Code:
stack=2, locals=2, args_size=2
0: iload_1
1: ifle 12
4: getstatic #47 // Field java/lang/System.out:Ljava/io/PrintStream;
7: ldc #85 // String positive x
9: invokevirtual #55 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
12: iload_1
13: ineg
14: ireturn
StackMapTable: number_of_entries = 1
frame_type = 12 /* same */
Run Code Online (Sandbox Code Playgroud)
现在,我将SFM更改为包含以下内容:
StackMapTable: number_of_entries = 1
frame_type = 255 /* full_frame …Run Code Online (Sandbox Code Playgroud) 我试图弄清楚方法的字节码大小,因为我想确保它足够小,以便通过编译器优化来内联.
我看到内联方法的默认最大大小为35,所以如果方法大于该方法,我将修改代码或将其分解为多个方法.
我有一个生成下面的字节码的方法(通过IntelliJ IDEA的ASM字节码大纲插件进行反汇编).
如何判断该方法的字节码大小?LINENUMBER似乎引用了原始源代码的行号.
TIA
public static mergeNativeArrays([Ljava/lang/Object;[Ljava/lang/Object;IZ)[Ljava/lang/Object;
L0
LINENUMBER 865 L0
ALOAD 0
ASTORE 4
L1
LINENUMBER 867 L1
ILOAD 2
IFGE L2
L3
LINENUMBER 868 L3
ALOAD 0
ARRAYLENGTH
ISTORE 2
L2
LINENUMBER 870 L2
FRAME APPEND [[Ljava/lang/Object;]
ILOAD 2
ALOAD 1
ARRAYLENGTH
IADD
ISTORE 5
L4
LINENUMBER 872 L4
ALOAD 4
ARRAYLENGTH
ILOAD 5
IF_ICMPGE L5
L6
LINENUMBER 874 L6
ILOAD 3
IFEQ L7
L8
LINENUMBER 875 L8
ILOAD 5
INVOKESTATIC railo/commons/math/MathUtil.nextPowerOf2 (I)I
ISTORE 5
L7 …Run Code Online (Sandbox Code Playgroud) 列表推导将其代码直接放在使用它们的函数中,如下所示:
>>> dis.dis((lambda: [a for b in c]))
1 0 BUILD_LIST 0
3 LOAD_GLOBAL 0 (c)
6 GET_ITER
>> 7 FOR_ITER 12 (to 22)
10 STORE_FAST 0 (b)
13 LOAD_GLOBAL 1 (a)
16 LIST_APPEND 2
19 JUMP_ABSOLUTE 7
>> 22 RETURN_VALUE
Run Code Online (Sandbox Code Playgroud)
而生成器表达式和字典/集合理解主要放在一个单独的嵌套函数中,如下所示:
>>> dis.dis((lambda: {a for b in c}))
1 0 LOAD_CONST 1 (<code object <setcomp> at 0x7ff41a3d59b0, file "<stdin>", line 1>)
3 MAKE_FUNCTION 0
6 LOAD_GLOBAL 0 (c)
9 GET_ITER
10 CALL_FUNCTION 1
13 RETURN_VALUE
>>> dis.dis((lambda: {a for …Run Code Online (Sandbox Code Playgroud) 我正在使用ByteBuddy在运行时使用动态生成的字节代码创建一个类.生成的类执行它要执行的操作,但我想手动检查生成的字节代码,以确保它是正确的.
例如
Class<?> dynamicType = new ByteBuddy()
.subclass(MyAbstractClass.class)
.method(named("mymethod"))
.intercept(new MyImplementation(args))
.make()
.load(getClass().getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
.getLoaded();
Run Code Online (Sandbox Code Playgroud)
其中MyImplementation将多个StackManipulation命令链接在一起以创建动态生成的代码.
我可以将生成的类编写到文件中(因此我可以使用IDE手动检查),或者打印出生成的类的字节码吗?
我正在学习ASM库来生成字节码.在某些时候我犯了一些错误的局部变量类型,并得到一个错误:
Exception in thread "main" java.lang.VerifyError: Bad local variable type
Exception Details:
Location:
Loops.start()V @56: aload_1
Reason:
Type top (current frame, locals[1]) is not assignable to reference type
Stackmap Table:
full_frame(@24,{Object[#2],Object[#9]},{Integer})
full_frame(@25,{Object[#2],Object[#9]},{Integer,Integer})
same_locals_1_stack_item_frame(@44,Integer)
full_frame(@45,{Object[#2],Object[#9]},{Integer,Integer})
full_frame(@48,{Object[#2]},{Integer})
full_frame(@80,{Object[#2],Integer},{Integer})
full_frame(@81,{Object[#2],Integer},{Integer,Integer})
full_frame(@87,{Object[#2]},{Integer})
full_frame(@119,{Object[#2],Integer},{Integer})
full_frame(@120,{Object[#2],Integer},{Integer,Integer})
same_locals_1_stack_item_frame(@123,Integer)
Run Code Online (Sandbox Code Playgroud)
问题并不难找到并修复,但我很好奇这个堆栈图表是什么东西?
TL; DR
我正在寻找javac插件API,它允许我记录Java编译器为特定源文件所需的所有类.
更多的背景:
我正在写一个工具,从迁移Maven到Bazel所面临的挑战(和机会),一个在那儿是Bazel允许,并从的"模块"更细的粒度粮效益.另外,依赖关系对于编译类路径是不可传递的.
我试图构建代码的依赖关系图和已经使用的源代码字节码加上启发式(常量,进口等),但无意中发现了,而我害怕,只能通过使用来解决边界情况编译器插件.
给定的方法Foo中类Concrete,它接受的接口SomeInterface,其延伸ParentInterface然后javac需要两个SomeInterface和ParentInterface在编译类路径虽然ParentInterface在字节码或在源代码中不出现.
这是Maven因为依赖关系对编译类路径是传递的,但是我想避免这种情况,因为这极大地扩展了类路径(主要是关于源依赖性和构建触发的有趣).
我试图看看我是否可以使用编译器插件来识别编译器对给定源文件所需的所有类.这将对我有所帮助,因为我可以运行我的maven构建一次以收集信息,然后根据此信息生成图表.问题是我对API有点失落.
谢谢!
我正在使用一个相当古老的Java Ant项目,我将其导入到IntelliJ中,之前它是使用Eclipse开发的.该项目由少量servlet组成.我正在尝试从IntelliJ进行调试.IntelliJ可以在端口8000上连接到远程Tomcat,但是当我尝试添加断点时,我得到以下可怕的错误:
行号com.package.blah.SomeClass中没有行号信息
根据SO和其他地方的建议,我将我的Ant构建脚本修改为以下内容:
<target name="compile" depends="web-skeleton">
<ant dir="${deployment-wizard.dir}" target="uberjar"/>
<javac debug="true" debuglevel="lines,vars,source" srcdir="${src.dir}"
destdir="${build.dir}/WEB-INF/classes" classpathref="project.class.path"/>
</target>
Run Code Online (Sandbox Code Playgroud)
我将debug和debuglevel行添加到上面调用的目标javac.另外,我试过跑步javap -v SomeClass.class,在那里我看到如下内容:
line 94: 418
line 97: 433
line 98: 443
LocalVariableTable:
Start Length Slot Name Signature
343 22 13 decrypted Ljava/lang/String;
370 11 13 e Ljava/lang/Exception;
244 189 7 keyParam Ljava/lang/String;
255 178 8 userParam Ljava/lang/String;
266 167 9 environmentParam Ljava/lang/String;
Run Code Online (Sandbox Code Playgroud)
我不知道这是否意味着字节码包含行号,但它肯定是这样出现的.
我还尝试从头开始清理和重建,并从IntelliJ执行无效的缓存/重启.
我希望有人能在这里提供一些帮助.作为最后的手段,我可以尝试将其移植到Maven项目中,但除非绝对必要,否则我宁愿避免这种情况.
bytecode ×10
java ×8
python ×2
ant ×1
breakpoints ×1
byte-buddy ×1
compilation ×1
decompiler ×1
plugins ×1
pyc ×1