有时很难描述"我们的程序员"可能认为对非程序员和管理类型来说很简单的一些事情.
所以...
您如何描述托管代码(或Java字节代码)与非托管/本机代码之间的区别?
我正在寻找一种在JVM类文件和文本表示之间往返的故障安全方法,然后再返回.
一个严格的要求是,只要文本表示保持不变,生成的往返JVM类文件在功能上与原始JVM类文件完全等效.
此外,文本表示必须是人类可读和可编辑的.应该可以对文本表示进行小的更改(例如更改文本字符串或类名等),这些更改会反映在生成的类文件表示中.
最简单的解决方案是使用Java反编译器(如JAD)生成文本表示,在这种情况下,它只是重新创建的Java源代码.然后使用javac生成字节码.但是,鉴于免费Java反编译器的状态,这种方法在所有情况下都不起作用.创建混淆的字节代码相当容易,这些字节代码不能在完整的往返类文件/ java-source/class-file中存活(部分原因是因为JVM字节代码之间没有1:1的映射) Java源代码).
根据上述要求,是否存在实现JVM类文件/文本表示/类文件往返的故障安全方法?
更新:在回答之前 - 通过阅读上述所有要求节省时间和精力,并特别注意:
class A { void F() { System.out.println("a"); }}
class B extends A { void F() { System.out.println("b"); }}
public class X {
public static void main(String[] args) {
A objA = new B();
objA.F();
}
}
Run Code Online (Sandbox Code Playgroud)
这里F()是动态调用的,不是吗?
这篇文章说:
... Java字节码不支持动态方法调用.有三种受支持的调用模式:invokestatic,invokespecial,invokeinterface或invokevirtual.这些模式允许调用具有已知签名的方法.我们谈论强类型语言.这允许在编译时直接进行一些检查.
另一方面,动态语言使用动态类型.所以我们可以在编译时调用一个未知的方法,但是使用Java字节码完全不可能.
我错过了什么?
我有时会在其他人看到代码"while 1"而不是"while True".我认为使用True更加pythonic,但我想检查练习中是否有任何差异.
所以我尝试做以下事情,结果令人惊讶.对于我所看到的,看起来解释器可以优化掉1布尔转换,而不是True,与我想的相反.
任何人都可以解释我为什么会这样,或者说我的结论可能是错的?
def f1():
while 1:
pass
def f2():
while True:
pass
In [10]: dis.dis(f)
2 0 SETUP_LOOP 3 (to 6)
3 >> 3 JUMP_ABSOLUTE 3
>> 6 LOAD_CONST 0 (None)
9 RETURN_VALUE
In [9]: dis.dis(f1)
2 0 SETUP_LOOP 10 (to 13)
>> 3 LOAD_GLOBAL 0 (True)
6 POP_JUMP_IF_FALSE 12
3 9 JUMP_ABSOLUTE 3
>> 12 POP_BLOCK
>> 13 LOAD_CONST 0 (None)
16 RETURN_VALUE
Run Code Online (Sandbox Code Playgroud) 我记得在Java字节码中没有看到任何引用变量类型的概念.我对类型擦除有点了解,但是这个术语似乎与泛型紧密相关,而我的问题一般是关于对象引用变量.Java对象引用变量类型是否在编译后存活?或者变量类型只是起到帮助编译器帮助开发人员检查代码是否有意义的作用?如果引用变量类型在编译中存活,它们在字节码中出现在哪里?
编辑:请允许我在此感谢您的宝贵贡献.为了更多地考虑我的想法,我想补充一个例子:
Object o = "foo";
Run Code Online (Sandbox Code Playgroud)
在字节码中,变量o及其类型(Object)是否可以在任何地方表示并在运行时读取?
是否有可能从HHVM权威仓库文件中恢复源代码?在本地安装我的商业SaaS产品时,我想使用HHVM进行基本的防篡改.
我想(还没检查)sqlite3 db包含字节码,并且鉴于PHP的动态性质,变量名称..因为*.pyc可以以一种非常直接的方式反转,我应该假设这里可能相同吗?即使目前没有工具可用?
我很难理解Byte Buddy的文档.为了帮助我学习API,我想生成与此Java相当的字节代码:
public final class GeneratedByByteBuddy {
private final int a;
public GeneratedByByteBuddy(final int a) {
this.a = a;
}
}
Run Code Online (Sandbox Code Playgroud)
我很难找到正确的方法Instrumentation来创建字段分配.
在类文件的字节码中javap -c ...,有一个代码块负责初始化类中的静态字段.但是,有两个if语句,ifne并且ifeq相互放置:
27: ifne 120
30: ifeq 119
Run Code Online (Sandbox Code Playgroud)
初始化块位于偏移量37和115之间,并且是初始化类中包含的静态变量所必需的.我的理解是,ifne如果堆栈上的值不为0,ifeq则会进行分支,如果堆栈上的值为0,则会跳转,这意味着它将分支.
我的问题是:如果初始化块只是被这些分支跳过,为什么变量稍后会被初始化?我找不到任何分支到块,所以如果代码在其他地方分支,它怎么能运行?
编辑:更多字节码
0: getstatic #602 // static integer field
3: istore 25
...
25: iload 25
27: ifne 120
30: ifeq 119
33: goto 37
36: athrow
37: new #6 // class java/io/File
40: dup
41: getstatic #615 // static string containing filename
...
56: invokespecial #9 // Method java/io/File."<init>":(Ljava/lang/String;)V
...
112: putstatic #14 // static File referenced later on
Run Code Online (Sandbox Code Playgroud) 我目前正在编写一个程序来读取java类文件.目前,我正在读取类文件的Constant-Pool(在此处阅读)并将其打印到控制台.但是当它被打印出来时,一些unicode似乎以这种方式弄乱我的终端,它看起来像这样(如果重要的话,我正在阅读的类文件是从Kotlin编译的,而终端I我使用的是IntelliJ IDEA终端,虽然在使用常规Ubuntu终端时似乎没有出现问题.):
我注意到的是一个奇怪的Unicode序列,我认为它可能是某种逃逸序列.
这是没有奇怪的unicode序列的整个输出:
{1=UTF8: (42)'deerangle/decompiler/main/DecompilerMainKt', 2=Class index: 1, 3=UTF8: (16)'java/lang/Object', 4=Class index: 3, 5=UTF8: (4)'main', 6=UTF8: (22)'([Ljava/lang/String;)V', 7=UTF8: (35)'Lorg/jetbrains/annotations/NotNull;', 8=UTF8: (4)'args', 9=String index: 8, 10=UTF8: (30)'kotlin/jvm/internal/Intrinsics', 11=Class index: 10, 12=UTF8: (23)'checkParameterIsNotNull', 13=UTF8: (39)'(Ljava/lang/Object;Ljava/lang/String;)V', 14=Method name index: 12; Type descriptor index: 13, 15=Bootstrap method attribute index: 11; NameType index: 14, 16=UTF8: (12)'java/io/File', 17=Class index: 16, 18=UTF8: (6)'<init>', 19=UTF8: (21)'(Ljava/lang/String;)V', 20=Method name index: 18; Type descriptor index: 19, 21=Bootstrap method attribute index: 17; NameType index: 20, 22=UTF8: (15)'getAbsolutePath', 23=UTF8: …Run Code Online (Sandbox Code Playgroud) 我对Java字节码世界非常陌生。我有一些涉及字节码的调试任务。在浏览时,我注意到一些看起来可疑的值,但我不确定。这是完整字节码的一部分
// access flags 0x100A
private static synthetic $jacocoInit()[Z
GETSTATIC ClassUnderTest.$jacocoData : [Z
DUP
IFNONNULL L0
POP
LDC -1475355800743669619
LDC "ClassUnderTest"
BIPUSH 64
INVOKESTATIC org/jacoco/agent/rt/internal_1f1cc91/Offline.getProbes (JLjava/lang/String;I)[Z
DUP
PUTSTATIC ClassUnderTest.$jacocoData : [Z
L0
Run Code Online (Sandbox Code Playgroud)
我最关心的是LDC -1475355800743669619。到目前为止,我了解到的是,这是一个类中用于常量值的字段。
如果LDC值可以为负,我会感到困惑吗?
我遇到的另一个问题是,对于JDK-8,同一类的LDC值为正,但是对于JDK-11,它为负。所以我的问题是,它也依赖于JDK吗?
bytecode ×10
java ×7
jvm ×3
byte-buddy ×1
classloader ×1
compilation ×1
decompiling ×1
dynamic ×1
hhvm ×1
interpreter ×1
jacoco ×1
java-11 ×1
managed ×1
obfuscation ×1
php ×1
python ×1
reference ×1
unicode ×1
unmanaged ×1
variables ×1