Java虚拟机知识分享
🏐🏐 知识改变命运🏐🏐
🏀🏀 knowledge is power🏀🏀
- 参考书籍:《深入Java虚拟机第二版》
JVM和JRE、JDK的关系
- JVM:Java Virtual Machine,负责执行符合规范的Class文件
- JRE:Java Runtime Environment,包含JVM和类库
- JDK:Java Development Kit,包含JRE和一些开发工具,如javac
1.Java的体系结构
Java体系结构
- Java的程序语言设计
- Java class文件格式
- Java应用编程接口(API)
- Java虚拟机
重点:
- Java技术的核心就是Java虚拟机,所有的Java程序都在其上运行
- Java虚拟机的主要任务就是装载class文件并且执行其中的字节码
2.Java虚拟机生命周期
- 一个运行时的java虚拟机实例的天职就是负责运行一个java程序,当程序启动时,一个java虚拟机实例就诞生了,当程序退出时,这个虚拟机实例也随之消亡。
- java虚拟机实例通过调用某个类的main()方法,这个main()方法必须是共有的(public),静态的(static),返回值为void
- 在java虚拟机内部有两种线程,守护线程和非守护线程,守护线程通常是由虚拟机自己使用的,比如执行垃圾回收机制,而执行的java程序,则是非守护线程
3.Java虚拟机的体系结构
Java虚拟机内存模型:
- 两个子系统为:class loader(类装载)、Execution engine(执行引擎)
- 两个组件为:Runtimedata area(运行时数据区)、Native interface(本地接口)
- 如果把JVM比作一个人,那么class文件就是人吃的食物。
- 加载class文件的是一个叫做类加载器的子系统。就好比嘴巴,把食物吃到肚子里。
- 执行引擎用来执行class文件中的字节码指令。就好比人们的肠胃,对吃进去的食物进行消化。
- 在执行过程中,要分配内存创建对象。当这些对象过时无用了,必须要自动清理这些无用的对象。清理对象回收内存的任务由垃圾收集器负责。就好比人吃进去的食物,在消化之后,必须把废物排出体外,腾出空间可以在下次饿的时候吃饭并消化食物。
栈是运行时的单位,而堆是存储的单位
- 栈 -> 解决程序的运行问题,即方法如何执行。
- 堆 -> 解决数据存储的问题,即数据怎么放,放哪里。
栈的特点(stack):
- Java虚拟机栈会为每一个即将执行的方法创建一块“栈帧”,这块区域就是专门用来存放方法在运行过程中所需要的信息。
- Java栈的特性就是先进后出,后进先出
- Java栈都是向下生长的
一个线程执行后,每调用一个方法,虚拟机就会压入一个新的栈针到该线程的java栈中,方法执行完,这个栈针就会从该java栈中弹出并抛弃。
堆的特点(heap):
- java程序在运行时创建的所有类实例或数组都放在同一个堆中
- 一个java程序独占一个java虚拟机实例,所以每个java程序都有自己的堆空间
- 一个java程序有多个线程,会共享一个堆空间
- 堆空间可以不是连续的,并且可以动态扩展或者收缩
方法区:
- 方法区是一块所有线程共享的内存区域,用于保存系统的类信息,有字段信息、方法、常量池,除常量以外的所有类静态变量,一个到类ClassLoader的引用,一个到Class类的引用。
- 字段信息包括:字段名,字段的类型,字段的修饰符
- 方法包括:方法名,方法的返回值类型,方法的参数类型和数量,方法的修饰符
- 常量池:就是该类所有常量的一个有序集合,包括直接常量(String,integer…)和对其他类,字段,方法的符号引用
- jdk6和jdk7中,方法区可以理解为永久区(Perm).
- jdk8中永久区被移除了,取而代之的是元数据区
4.数据类型
5.垃圾回收
- Java 内存运行时区域的各个部分,其中程序计数器、虚拟机栈、本地方法栈三个区域随线程共存亡。栈中的每一个栈帧分配多少内存基本上在类结构确定下来时就已知,因此这几个区域的内存分配和回收都具有确定性,不需要考虑如何回收的问题,当方法结束或线程结束,内存自然也跟着回收了
- 垃圾回收机制处理的是堆中存放的所有java程序创建的对象,所以我叫它 垃圾堆,其实还有方法区。
- 当对象不再被程序引用,垃圾回收器将运行对象的终结方法finalizer
- 引用计数法
- 可达性分析法法
以根对象作为起始节点集,从这些节点开始,根据引用关系向下搜索,搜索过程走过的路径称为引用链。如果某个对象到根节点间没有任何引用链相连,则证明此对象是不可能再被使用,可以回收- 四种引用类型
强引用、软引用、弱引用、虚引用- 这里太复杂。。。
5.1 内存溢出
- 内存溢出:就是指程序运行过程中申请的内存大于系统能够提供的内存,导致无法申请到足够的内存,于是就发生了内存溢出.
- java.lang.OutOfMemoryError: PermGen space (持久带溢出)
- 运行时常量池溢出
- java.lang.OutOfMemoryError: Java heap space (堆溢出)
- 创建的对象太多,在进行垃圾回收之前对象数量达到了最大堆的容量限制
- StackOverflowError
- 线程请求的栈深度大于虚拟机所允许的最大深度。
- OutOfMemoryError
- 虚拟机在扩展栈时无法申请到足够的内存空间。
5.1 内存泄露
- 内存泄漏:指程序运行过程中分配内存给临时变量,用完之后却没有被GC回收,始终占用着内存,既不能被使用也不能分配给其他程序,于是就发生了内存泄漏.
- 报警:memory leak