随笔 - 1162  文章 - 0  评论 - 16  阅读 - 59万 

一、概述

  1、字节码文件的跨平台性

    (1)Java语言:跨平台的语言(write once ,run anywhere)
      当Java源代码成功编译成字节码后,如果想在不同的平台上面运行,则无须再次编译这个优势不再那么吸引人了。Python、PHP、Per1、Ruby、Lisp等有强大的解释器。·跨平台似乎已经快成为一门语言必选的特性。

    (2)Java虚拟机:跨语言的平台
      Java虚拟机不和包括Java在内的任何语言绑定,它只与“Class 文件”这种特定的二进制文件格式所关联。无论使用何种语言进行软件开发,只要能将源文件编译为正确的Class文件,那么这种语言就可以在Java虚拟机上执行。可以说,统一而强大的
Class文件结构,就是Java虚拟机的基石、桥梁。

      

         

 

          https://docs.oracle.com/javase/specs/index.html

      所有的JVM全部遵守Java虚拟机规范,也就是说所有的JVM环境都是一样的,。这样一来字节码文件可以在各种JVM上运行。

 

    (3)想要让一个Java程序正确地运行在JVM中,Java源码就必须要被编译为符合JVM规范的字节码。

      前端编译器的主要任务就是负责将符合Java语法规范的Java代码转换为符合JVM规范的字节码文件。

        javac是一种能够将Java源码编译为字节码的前端编译器。

        Javac编译器在将Java源码编译为一个有效的字节码文件过程中经历了4个步骤,分别是词法解析、语法解析、语义解析以及生成字节码

       

 

      Oracle的JDK软件包括两部分内容:

        一部分是将3ava源代码编译成Java虚拟机的指令集的编译器

        另一部分是用于实现ava虚拟机的运行时环境。

 

  2、Java的前端编译器

 

 

  前端编译器 VS 后端编译器

 

  Java源代码的编译结果是字节码,那么肯定需要有一种编译器能够将Java源码编译为字节码,承担这个重要责任的就是配置在path环境变量中的javac编译器。javac是一种能够将Java源码编译为字节码的前端编译器


  HotSpot VM并没有强制要求前端编译器只能使用javac来编译字节码,其实只要编译结果符合JVW规范都可以被JVM所识别即可。在Java的前端编译器领域,除了javac之外,还有一种被大家经常用到的前端编译器,那就是内置在Eclipse中的ECJ(EclipseCompiler for Java)编译器。和Javac的全量式编译不同,ECJ是一种增量式编译器。

    (1)在Eclipse中,当开发人员编写完代码后,使用“Ctrl+S”快捷键时,ECJ编译器所采取的编译方案是把未编译部分的源码逐行进行编译,而非每次都全量编译。因此ECJ的编译效率会比javac更加迅速和高效,当然编译质量和javac相比大致还是一样的。

    (2)ECJ不仅是Eclipse的默认内置前端编译器,在Tomcat中同样也是使用ECJ编译器来编译jsp文件。由于ECJ编译器是采用 GPLv2 的开源协议进行源代码公开,所以,大家可以登录eclipse官网下载ECJ编译器的源码进行二次开发。

    (3)默认情况下,Intelli3 IDEA使用 javac编译器。(还可以自己设置为Aspect]编译器 ajc )


  前端编译器并不会直接涉及编译优化等方面的技术,而是将这些具体优化细节移交给HotSpot的JIT编译器负责。


  复习:AOT(静态提前编译器,Ahead Of Time Compiler)

 

  3、透过字节码指令看代码细节

    面试题:

    ① 类文件结构有几个部分?

    ② 知道字节码吗?字节码都有哪些?Integer x = 5; int y = 5; 比较 x==y 都经过哪些步骤?

    案例1:

复制代码
 1 public class IntegerTest {
 2 
 3     public static void main(String[] args) {
 4         Integer x = 5;
 5         int y = 5;
 6         System.out.println(x == y);  //true
 7 
 8         Integer i1 = 10;
 9         Integer i2 = 10;
10         System.out.println(i1 == i2); //true
11 
12         Integer i3 = 128;
13         Integer i4 = 128;
14         System.out.println(i3 == i4); //false
15     }
16 }
复制代码

 

      字节码信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
0 iconst_5  把int 5 放在操作数栈
 1 invokestatic #2 <java/lang/Integer.valueOf>  调用valueOf成为包装类
 4 astore_1     
 5 iconst_5
 6 istore_2
 7 getstatic #3 <java/lang/System.out>
10 aload_1
11 invokevirtual #4 <java/lang/Integer.intValue>
14 iload_2
15 if_icmpne 22 (+7)
18 iconst_1
19 goto 23 (+4)
22 iconst_0
23 invokevirtual #5 <java/io/PrintStream.println>
26 bipush 10
28 invokestatic #2 <java/lang/Integer.valueOf>
31 astore_3
32 bipush 10
34 invokestatic #2 <java/lang/Integer.valueOf>
37 astore 4
39 getstatic #3 <java/lang/System.out>
42 aload_3
43 aload 4
45 if_acmpne 52 (+7)
48 iconst_1
49 goto 53 (+4)
52 iconst_0
53 invokevirtual #5 <java/io/PrintStream.println>
56 sipush 128
59 invokestatic #2 <java/lang/Integer.valueOf>
62 astore 5
64 sipush 128
67 invokestatic #2 <java/lang/Integer.valueOf>
70 astore 6
72 getstatic #3 <java/lang/System.out>
75 aload 5
77 aload 6
79 if_acmpne 86 (+7)
82 iconst_1
83 goto 87 (+4)
86 iconst_0
87 invokevirtual #5 <java/io/PrintStream.println>
90 return

 

 

 

    案例2:

复制代码
1 public class StringTest {
2     public static void main(String[] args) {
3         String str = new String("hello") + new String("world");
4         String str1 = "helloworld";
5         System.out.println(str == str1);   //false
6     }
7 }
复制代码

 

       字节码信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
0 new #2 <java/lang/StringBuilder>
 3 dup
 4 invokespecial #3 <java/lang/StringBuilder.<init>>
 7 new #4 <java/lang/String>
10 dup
11 ldc #5 <hello>
13 invokespecial #6 <java/lang/String.<init>>
16 invokevirtual #7 <java/lang/StringBuilder.append>
19 new #4 <java/lang/String>
22 dup
23 ldc #8 <world>
25 invokespecial #6 <java/lang/String.<init>>
28 invokevirtual #7 <java/lang/StringBuilder.append>
31 invokevirtual #9 <java/lang/StringBuilder.toString>
34 astore_1
35 ldc #10 <helloworld>
37 astore_2
38 getstatic #11 <java/lang/System.out>
41 aload_1
42 aload_2
43 if_acmpne 50 (+7)
46 iconst_1
47 goto 51 (+4)
50 iconst_0
51 invokevirtual #12 <java/io/PrintStream.println>
54 return

  

 

    案例3:

复制代码
 1 class Father {
 2     int x = 10;
 3     public Father() {
 4         this.print();
 5         x = 20;
 6     }
 7 
 8     public void print() {
 9         System.out.println("Father.x = " + x);
10     }
11 }
12 
13 class Son extends Father {
14     int x = 30;
15     public Son() {
16         this.print();
17         x = 40;
18     }
19 
20     public void print() {
21         System.out.println("Son.x = " + x);
22     }
23 }
24 public class SonTest {
25     public static void main(String[] args) {
26         Father f = new Son();
27         System.out.println(f.x);   
28     }
29 }
复制代码

 

 

 

        运行结果:

1
2
3
Son.x = 0
Son.x = 30
20

  

      字节码信息:

      Father类:

1
2
3
4
5
6
7
8
9
10
11
0 aload_0
 1 invokespecial #1 <java/lang/Object.<init>>
 4 aload_0
 5 bipush 10
 7 putfield #2 <com/njf/java/Father.x>
10 aload_0
11 invokevirtual #3 <com/njf/java/Father.print>
14 aload_0
15 bipush 20
17 putfield #2 <com/njf/java/Father.x>
20 return

      Son类:

1
2
3
4
5
6
7
8
9
10
11
0 aload_0
 1 invokespecial #1 <com/njf/java/Father.<init>>
 4 aload_0
 5 bipush 30
 7 putfield #2 <com/njf/java/Son.x>
10 aload_0
11 invokevirtual #3 <com/njf/java/Son.print>
14 aload_0
15 bipush 40
17 putfield #2 <com/njf/java/Son.x>
20 return

      SonTest类:

1
2
3
0 aload_0
1 invokespecial #1 <java/lang/Object.<init>>
4 return

  

二、虚拟机的基石:Class 文件

三、Class 文件结构

四、使用 javap 指令解析 Class 文件

五、

六、

posted on   格物致知_Tony  阅读(86)  评论(0编辑  收藏  举报
编辑推荐:
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· .NET Core 托管堆内存泄露/CPU异常的常见思路
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· DeepSeek R1 简明指南:架构、训练、本地部署及硬件要求
· 没有源码,如何修改代码逻辑?
· NetPad:一个.NET开源、跨平台的C#编辑器
点击右上角即可分享
微信分享提示

目录导航