jdk中的文件
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.txthw.txt
Compiled from "HelloWorld.java" public class example.HelloWorld { public example.HelloWorld(); Code: 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":()V 4: return public static void main(java.lang.String[]); Code: 0: new #2 // class example/HelloWorld 3: dup 4: invokespecial #3 // Method "<init>":()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
