JVM原理
-
java自动管理堆(heap)和(栈),程序员不能直接的设置堆和栈。
-
在操作系统中
- 堆:一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收,分配方式类似于链表。
- 栈:由操作系统自动分配释放,存放函数的参数值,局部变量值等。操作方式与数据结构中的栈相类似
GC机制:在jvm中,程序计数器、虚拟机栈、本地方法栈都是随线程而生随线程而灭,栈帧随着方法的进入和退出做入栈和出栈操作,实现了自动的内存清理。所以,内存垃圾回收主要集中于 java 堆和方法区中,在程序运行期间,这部分内存的分配和使用都是动态的。
如果jvm放在栈中,java的一个null对象就很难确定会被谁回收了。要对栈做到自动释放也是jvm需要考虑的,所以需要放在堆中,动态分配和使用。
GC垃圾回收机制不是创建的变量为空是就被立刻回收,而是超出变量的作用域后就被自动回收。
-
堆和方法区
特性 堆 方法区 存储内容 对象实例、数组 类元信息(构造方法/接口定义)、静态变量、方法字节码、常量 线程共享 是 是 GC 影响 是 GC 主要处理区域 受 GC 管理,但优先级较低 实现方式 直接由 JVM 管理 永久代(JDK 7 及以前)、元空间(JDK 8 及以后) 大小限制 通过 -Xms
和-Xmx
设置通过 -XX:MetaspaceSize
设置方法区仅仅只是逻辑上的独立,实际上还是包含在Java堆中,
永久区(Permanent Generation)
就是方法区的实现。 -
jvm虚拟机位于操作系统的堆中,程序员写好的类加载到虚拟机执行的过程是:
- Java 中的类加载由 类加载器(ClassLoader) 负责,classLoader启动于jvm中的堆,去主机硬盘或网络上将A.class文件装载到jvm的方法区,生成与该类相关的类元信息。
- JVM 会在 堆中 为该类生成一个 Class 对象,这个对象是对方法区中类元信息(A字节码的内存文件)的引用,用于程序运行时访问这些元信息。程序在运行时通过 Class 对象 反射访问类的信息。(我们看到的就是 对象.属性)
- 方法区中的类元数据还需要记录它是由哪个 ClassLoader 加载的。有助于 JVM 管理类的加载和卸载,因为不同的类加载器可以加载同名的类而不冲突。
-
java虚拟机的生命周期:一个java应用main函数启动时虚拟机也同时被启动,当在虚拟机实例中的所有非守护线程都结束时,java虚拟机实例才结束生命。
- 守护线程和非守护线程。守护线程通常是由虚拟机自己使用的,比如执行垃圾收集任务的线程(比如虚拟机的GC)。 但是,Java程序也可以把它创建的任何线程标记为守护线程。而Java程序中的初始线程-就是开始于main()的那个是非守护线程。 只要还有任何非守护线程在运行,那么这个Java程序也在继续运行(虚拟机仍然存活)。当程序中的所有的非守护线程都终止时,虚拟机实例自动退出。
-
java虚拟机与main方法的关系:启动了几个main函数就启动了几个java应用,同时也启动了几个java的虚拟机。
-
程序在jvm运行的流程:当一个程序启动之前,它的class会被类装载器装入方法区,执行引擎读取方法区的字节码自适应解析,边解析就边运行(其中一种方式),然后pc寄存器指向了main函数所在位置,虚拟机开始为main函数在java栈中预留一个栈帧(每个方法都对应一个栈帧),然后开始跑main函数,main函数里的代码被执行引擎映射成本地操作系统里相应的实现,然后调用本地方法接口,本地方法运行的时候,操纵系统会为本地方法分配本地方法栈,用来储存一些临时变量,然后运行本地方法,调用操作系统API等等。
-
jdk,jre,JVM的关系:JDK(Java Development Kit) 是 Java 语言的软件开发工具包(SDK)。在JDK的安装目录下有一个jre目录,里面有两个文件夹bin和lib,在这里可以认为bin里的就是jvm,lib中则是jvm工作所需要的类库,而jvm和 lib合起来就称为jre。
JVM先了解这么多,下一篇步入正题。ClassLoader
图片来源:[ClassLoader · 攻击Java Web应用-Java Web安全]