bin:最主要的是编译器javac.exe
include:java和jvm交互的头文件
lib:类库
jre:java运行环境
金字塔结构 JDK=JRE+JVM+其它 运行Java程序一般都要求用户的电脑安装JRE环境(Java Runtime Environment);没有jre,java程序无法运行;而没有java程序,jre就没有用武之地。
包括两种:Client VM 和 Server VM
Client VM(-client),为在客户端环境中减少启动时间而优化;
Server VM(-server),为在服务器环境中最大化程序执行速度而设计。
比较:Server VM启动比Client VM慢,运行比Client VM快。
配置文件的位置如下:
若为64位操作系统
{JRE_HOME}/lib/amd64/jvm.cfg
若为32位操作系统
{JRE_HOME}/lib/i386/jvm.cfg
配置文件里面第一行写的是 -client 默认就是client版本,把第二行的-server KNOWN 放到第一行,就会变成sercer版本,如下面所示:
也可以在控制命令台搜java -version,查看虚拟机类型
“一次编译,到处运行”
不同的操作系统,底层的指令是不同的,底层的指令只能识别机器码(01001011)
java虚拟机从软件层面屏蔽了底层硬件指令层面的细节
Java之所以可以做到跨平台,是因为Java虚拟机充当了桥梁。他扮演了运行时Java程序与其下的硬件和操作系统之间的缓冲角色。
问题:C/C++可以跨平台吗?
C/C++是编译时跨屏台,Java是运行时跨平台。
首先通过类加载器(ClassLoader)会把编译后的字节码文件加载入内存中,
运行时数据区(Runtime Data Area)再把字节码加载到内存中,而字节码文件只是 JVM 的一套指令集规范,并不能直接交个底层操作系统去执行,
因此需要特定的命令解析器执行引擎(Execution Engine),将字节码翻译成底层系统指令,再交由 CPU 去执行,
而这个过程中需要调用其他语言的本地库接口(Native Interface)来实现整个程序的功能。
堆——存放对象,线程共享;
栈——执行程序,线程私有;
HelloWorld.java
package example;
/**
* @Author:liujiamei
* @Date:2020/5/28 8:16
* @Version 1.0
*/
public class HelloWorld {
public static void main(String[] argv) {
HelloWorld hw = new HelloWorld();
int result = hw.add();
System.out.println(result);
}
/**
* 计算方法,局部变量
* 一个方法为一个栈帧:以方法进行数据隔离
* @return
*/
public int add() {
int a, b, c;//存储在add方法的局部变量表中
a = 1;
b = 2;
c = a + b;
return c;
}
}
HelloWorld.class字节码文件
javap代码反汇编
javap
javap -c HelloWorld.class
>javap -c HelloWorld.class>hw.txt
hw.txt
Compiled from "HelloWorld.java"
public class example.HelloWorld {
public example.HelloWorld();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."":()V
4: return
public static void main(java.lang.String[]);
Code:
0: new #2 // class example/HelloWorld
3: dup
4: invokespecial #3 // Method "":()V
7: astore_1
8: aload_1
9: invokevirtual #4 // Method add:()I
12: istore_2
13: getstatic #5 // Field java/lang/System.out:Ljava/io/PrintStream;
16: iload_2
17: invokevirtual #6 // Method java/io/PrintStream.println:(I)V
20: return
public int add();
Code: //线程的程序计数器:指向当前字节码指令的(地址)行号
0: iconst_1 //将int类型常量1压入栈,将1放入操作数栈
1: istore_1 //将int类型值存入局部变量1,a=1
2: iconst_2
3: istore_2
4: iload_1 //从局部变量1装载int类型值,再压入操作数栈
5: iload_2
6: iadd //执行int类型的加法,1和2出栈,1+2=3,
7: istore_3 //3压入操作数栈,此时操作数栈只有3
8: iload_3
9: ireturn //从方法中返回int类型的数据,通过方法出口返回给main方法
}
jvm指令集代码 https://blog.csdn.net/zhangpan19910604/article/details/52254053