在Java中,"二进制代码"是否与"Java字节码"相同?
这是Java中的流程吗?
Java文件(.java) - > [javac] - > ByteCode文件(.class) - > [JVM/Java解释器] - >运行它(首先将其转换为特定于机器的二进制代码)
谢谢!
在寻找源代码,字节码,汇编代码,机器代码,编译器,链接器,解释器,汇编器和其他所有内容的各种差异时,我只对编码和汇编代码之间的区别感到困惑.
特别是介绍这篇维基百科文章来描述CIL让我很困惑,因为它似乎可以互换地使用这两个术语(汇编代码和字节码),这让我觉得它们可能意味着完全一样.
我在网上搜索并发现可以编译PHP代码以提高性能.但怎么办呢?我可以编译面向程序和面向对象的PHP代码吗?
如果你有像这样的匿名类
Predicate<String> isEmpty = new Predicate<String>() {
public boolean test(String t) {
return t.isEmpty();
}
};
Run Code Online (Sandbox Code Playgroud)
传递引用的库isEmpty可以检查字节代码以查看它的作用并可能对其进行操作.有没有办法可以为lambdas做到这一点?
Predicate<String> isEmpty = String::isEmpty;
Run Code Online (Sandbox Code Playgroud)
例如,假设有这个代码和字节码
public class Main {
public static void test(Predicate<String> tester) {
System.out.println("tester.getClass()= " + tester.getClass());
System.out.println("tester.getClass().getClassLoader()="+ tester.getClass().getClassLoader());
}
public static void main(String... args) {
Predicate<String> isEmpty = String::isEmpty;
test(isEmpty);
}
}
$ javap -cp . -c -private Main.class
Compiled from "Main.java"
public class Main {
public Main();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: …Run Code Online (Sandbox Code Playgroud) 为简单起见,想象一下这种情况,我们有一台2位计算机,它有一对2位寄存器,称为r1和r2,只适用于立即寻址.
让我们说比特序列00意味着添加到我们的CPU.也01的装置将数据移动到R 1和10组的装置将数据移动到R2.
因此,这台计算机和汇编程序有一个汇编语言,其中的示例代码将被编写为
mov r1,1
mov r2,2
add r1,r2
Run Code Online (Sandbox Code Playgroud)
简单地说,当我将此代码汇编为本机语言时,文件将类似于:
0101 1010 0001
Run Code Online (Sandbox Code Playgroud)
上面的12位是本机代码:
Put decimal 1 to R1, Put decimal 2 to R2, Add the data and store in R1.
Run Code Online (Sandbox Code Playgroud)
所以这基本上是编译代码的工作方式,对吧?
让我们说有人为这个架构实现了一个JVM.在Java中,我将编写如下代码:
int x = 1 + 2;
Run Code Online (Sandbox Code Playgroud)
JVM将如何解释此代码?我的意思是最终必须将相同的位模式传递给cpu,不是吗?所有cpu都有许多可以理解和执行的指令,它们毕竟只是一些位.让我们说编译的Java字节码看起来像这样:
1111 1100 1001
Run Code Online (Sandbox Code Playgroud)
或者其他..是否意味着解释在执行时将此代码更改为0101 1010 0001?如果是,它已经在本机代码中了,那为什么说JIT只是经过多次启动?如果它没有完全转换为0101 1010 0001,那么它会做什么?它如何使cpu做添加?
也许我的假设存在一些错误.
我知道解释很慢,编译代码更快但不可移植,虚拟机"解释"代码,但是如何?我正在寻找"如何完全/技术解释".任何指针(如书籍或网页)都是受欢迎的,而不是答案.
我们知道,在JDK8及以下版本中,使用加号进行拼接的字符串会被编译成StringBuilder来进行性能优化,但在JDK9之后,就会使用该java.lang.invoke.StringConcatFactory#makeConcatWithConstants方法来实现。
不过反编译后java.lang.Object可以看出,它的toString方法仍然是使用StringBuilder实现的:
public java.lang.String toString();
descriptor: ()Ljava/lang/String;
flags: (0x0001) ACC_PUBLIC
Code:
stack=2, locals=1, args_size=1
0: new #1 // class java/lang/StringBuilder
3: dup
4: invokespecial #3 // Method java/lang/StringBuilder."<init>":()V
7: aload_0
8: invokevirtual #7 // Method getClass:()Ljava/lang/Class;
11: invokevirtual #13 // Method java/lang/Class.getName:()Ljava/lang/String;
14: invokevirtual #19 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
17: ldc #23 // String @
19: invokevirtual #19 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
22: aload_0
23: invokevirtual #25 // Method hashCode:()I
26: invokestatic #29 // Method java/lang/Integer.toHexString:(I)Ljava/lang/String; …Run Code Online (Sandbox Code Playgroud) 是否可以将.class文件转换为.java文件?
如何才能做到这一点?
从此选项中提取的代码的正确性如何?
我想知道如何检查编译的Java类是否包含调试符号.问题是我使用debug ="on"从ant编译应用程序,但是特定的JVM会抛出异常:它表示缺少调试符号.
谢谢.
有时,在Eclipse中,我按下一组键,这些键将我带到显示我的.class文件(字节码)内容的编辑器页面.我似乎永远无法记住那个组合键是什么.
有人可以告诉我吗?
或者换句话说,如何看到自己的字节码?
我编写了这个简单的Test类来了解Java如何boolean在字节码级别评估代数:
public class Test {
private static boolean a, b;
public static boolean method1(){
return !(a || b);
}
public static boolean method2(){
return !a && !b;
}
}
Run Code Online (Sandbox Code Playgroud)
如果你简化method1()使用DeMorgan的法则,你应该得到method2().在查看字节码(使用javap -c Test.class)后,它看起来像:
Compiled from "Test.java"
public class Test {
public Test();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":
()V
4: return
public static boolean method1();
Code:
0: getstatic #2 // Field a:Z
3: ifne 16
6: getstatic #3 …Run Code Online (Sandbox Code Playgroud)