JVM :(java虚拟机)
一.首先第一步:(jvm 是什么)
JVM 是Java虚拟机,JVM是可运行 Java 代码的假想计算机 ,JVM 是运行在操作系统之上的,它与硬件没有直接的交互
二.组成部分:
堆,方法区,栈(java 虚拟栈),本地方法栈,程序计数器
运行过程:
java源文件,通过编译器,能够产生相应的 .class 文件,也就是字节码文件,而字节码文件又通过 Java 虚拟机(JVM)中的解释器,编译成特定机器上的机器码。
也就是如下:
① Java 源文件—->编译器—->字节码文件
② 字节码文件—->JVM—->机器码
备注:(java 跨平台原因)
平台就是指我们计算机的操作系统,例如:Windows、Linux、Mac等操作系统。
跨平台的意思就是Java程序,在一次编译后,在这些平台上都可以运行。
通过不同JVM实现Java程序的跨平台,window系统有专门的JVM,Linux也有专门的JVM,所以Java编译后的程序,能在这些操作系统上运行.
JVM 运行原理:
1.类装载器
类装载器(ClassLoader)主要负责加载 .class文件,有两种类加载器分别为启动类加载器和用户自定义类加载器,然而启动类加载器是JVM实现的一部分,用户自定义类加载器是Java程序一部分。
2.本地方法栈
主要作用是登记native方法,然后在execution engine执行的时候加载本地方法库。
(**注意:**区别于 Java 虚拟机栈的是,Java 虚拟机栈为虚拟机执行 Java 方法(也就是字节码)服务,而本地方法栈则为虚拟机使用到的 Native 方法服务。也会有 StackOverflowError 和 OutOfMemoryError 异常。)
3.Java 虚拟栈
(1)线程私有,栈有时我们又叫栈内存,负责Java程序的运行,它是在线程创建时创建的,所以生命周期也和线程的生命周期一样,同时消亡,线程结束栈也就释放了,(**特别提醒:**栈不存在垃圾回收的问题,因为线程结束栈就是释放了)
(2)描述的是Java 方法执行的内存模型:每个方法在执行时都会床创建一个栈帧(Stack Frame)用于存储局部变量表
、操作数栈
、动态链接
、方法出口
等信息。每一个方法从调用直至执行结束,就对应着一个栈帧从虚拟机栈中入栈到出栈的过程。
**局部变量表:**存放了编译期可知的各种基本类型(boolean、byte、char、short、int、float、long、double)、对象引用(reference 类型)和 returnAddress 类型(指向了一条字节码指令的地址)
注:
StackOverflowError:线程请求的栈深度大于虚拟机所允许的深度。
OutOfMemoryError:如果虚拟机栈可以动态扩展,而扩展时无法申请到足够的内存。
4.Java 堆
线程共享,主要是存放对象实例和数组。比我们在开发过程使用的new对象,只要通过new创建的对象的内存的对象都在堆分配。(**注意:**是垃圾收集器进行垃圾收集的最重要的内存区域【垃圾器GC 进行回收】)
5.方法区
属于共享内存区域,存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
运行时常量池 : 是方法区的一部分。Class 文件中除了有类的版本、字段、方法、接口等描述等信息外,还有一项信息是常量池,用于存放编译期生成的各种字面量和符号引用,这部分内容将在类加载后存放到方法区的运行时常量池中。
6.程序计数器
一块较小的内存空间, 是当前线程所执行的字节码的行号指示器,每条线程都要有一个独立的程序计数器,这类内存也称为“线程私有”的内存。正在执行 java 方法的话,计数器记录的是虚拟机字节码指令的地址(当前指令的地址)。如果还是 Native 方法,则为空。这个内存区域是唯一一个在虚拟机中没有规定任何 OutOfMemoryError 情况的区域。
。如果还是 Native 方法,则为空。这个内存区域是唯一一个在虚拟机中没有规定任何 OutOfMemoryError 情况的区域。