JVM的学习总结
- 首先我们要明白的是JVM、JDK、JRE三者的关系。JVM是简单的说就是一个虚拟机(运行容器);JDK是给开发者使用的一个工具包,里面包含了很多的jar包以及java的类库;JRE就是java程序运行的环境。三者的关系:JDK>JRE>JVM。
1、JVM存在的位置
- JVM简而言之就是一个容器,而他无法独自运行.class文件,他还需要java的类库,就是在JDK安装目录下lib目录里面的jar包。
- JVM就是存在于我们的操作系统之上,操作系统存在于电脑硬件(intel)之上。
2、运行时JVM的数据区域划分
- Java文件编译成.class文件,再由类加载器加载至虚拟机内。虚拟机主要分为:方法区、堆、栈、本地方法栈、程序计数器这是内部的数据区,在其外还有:执行引擎以及用于连接的本地方法接口。
(1)方法区:主要时存储一些静态变量、常量、类信息(构造方法、接口)、运行时候的常量池。他是所有变量共享的。
(2)堆:这个地方就是存储我们程序运行时产生的对象,通常我们所说的JVM调优就是调节堆的参数。
(3)栈:是一种数据结构,它主要存储的是8种数据类型、对象的引用所在、程序所要执行的方法。(压栈弹栈)
(4)本地方法栈:关键字Native,这个就是调用本地方法库的接口,java语言已无法控制,设置接口供java调用其他语言。
(5)执行引擎:它主要的职责便是编译、检查Java文件的规范性。
(6)本地方法接口、本地方法库
(7)内存空间小,线程私有。字节码的解析工作的秩序就是他完成的
(8)Native关键字在这说明一下,他是java调用其他语言的接口。
3、双亲委派机制以及类加载器的种类
- 类加载器有三种:启动类加载器、扩展类加载器PlatformClassLoader()、应用程序加载器AppClassLoader。他们都是加载class文件的。
- 重要
双亲委派机制:意思就是当一个类被加载的时候,它本身是不加载的,只会一直委派给父类加载器加载,直到启动类加载器看其是否可以加载,可以就结束,交予被委派的加载器加载,反则会抛出NotfoundClass。
4、沙箱机制
- 他的出现是为了java的安全。沙箱就是一个限制程序运行的环境。这个机制就是将java代码限定在虚拟机的特定的运行范围中,保证代码的有效隔离,防止对本地进行系统破坏,加了一个令牌限制。
5、JVM中栈的概念 程序=数据结构 + 算法
- 栈是一种数据结构,主要特点就是先进后出。注意他与队列的区别:队列就刚好与之相反就是先进先出。
栈中存在的东西:8大数据类型、class(引用,具体的实例是在堆里面)、实例方法
栈顶、栈底。 栈里面的结构:方法索引(index)、本地变量、class(引用)、输入输出参数、父帧、子帧。弹栈(先入栈先执行)
程序执行的方法一定在栈的顶部(栈满就会出现StackOverflowError栈满错误,递归调用就有可能出现栈满的情况)
6、栈、方法区和堆三者之间的关系
7、对象的创建过程
8、常见的JVM
- 常有的JVM : hotSpot、J9JVM(IBM) 、JRockit(BEM)
垃圾回收器以及常见的回收算法
1、基本概念
- 程序计数器、栈、本地方法栈 3 个区域随线程生灭(因为是线程私有),栈中的栈帧随着方法的进入和退出而有条不紊地执行着出栈和入栈操作。而 Java 堆和方法区则不一样,一个接口中的多个实现类需要的内存可能不一样,一个方法中的多个分支需要的内存也可能不一样,我们只有在程序处于运行期才知道那些对象会创建,这部分内存的分配和回收都是动态的,垃圾回收期所关注的就是这部分内存。
程序大部分的垃圾就存在于堆中,我们常见的JVM调优就是清除这里面的垃圾,以及改变相应的参数。
2、堆(heap,一个JVM只有一个JVM,内存可以调节)
新生区(伊甸区、辛存0区、辛存1区)、老年区、永久区
当没进行一次轻GC后,新生代的对象会从辛存0区移向辛存1区,对象经历15次轻GC后就会从新生代到老年代
堆满OOM:就是永久区的空间已满。比如大量加载jar包;大量生成很多类就会引起OOM。
虚拟机在进行轻GC之前会判断老年代最大的可用连续空间是否大于新生代的所有对象总空间
1、如果大于的话,直接执行轻GC
2、如果小于,判断是否开启HandlerPromotionFailure,没有开启直接重GC
3、如果开启了HanlerPromotionFailure, JVM会判断老年代的最大连续内存空间是否大于历次晋升的大小,如果小于直接执行重GC
4、如果大于的话,执行轻GC
执行重GC
1、老年代空间不足时
2、持久代空间不足
3、轻GC出现 promotion failure
4、当轻GC辛存对象大于,老年区现在的空间也会产生重GC
5、我们也可以系统调用进行重GC
堆内存调优的参数
-Xms1024m -Xmx1024m -XX:+PrintGCDetails调JVM参数
-Xms1m -Xmx8m -XX:+HeapDumpOnOutOfMemoryError Dump文件
3、如何判断是垃圾对象
- 有两种方法:引用计数法以及可达性分析法
引用计数法:就是找对象上面标记,当对象有引用指向它的时候至为1,当没有引用指向他的时候至为0.这样就可以区分对象是否为垃圾对象了。
可达性分析法:就和树形图类似,当节点没有路径到底根节点的时候可视为垃圾对象。引用计数法和可达性分析法
4、垃圾回收算法
- 复制算法
将辛存分为两块区域,直接将对象分成两边,这样做好处就是没有碎片空间,但也造成了大量的空间浪费。 - 标记清除算法
就是进行扫描并对对象进行标记,没有标记的对象进行清除,这样就会有大量的空间碎片。时间也会有大量的浪费。 - 标记清除压缩算法
是标记清除算法的改良。减少了空间发浪费 - 这三种算法各有优势和劣势,我们一般是根据事实的情况选取不同的算法。没有最好,只有合适–>GC:分代收集算法,每一代运用的算法都不同
三种算法的比较
内存效率:复制算法>标记清除>标记清除压缩(时间复杂度)
内存整齐度:复制算法=标记清除压缩>标记清除
内存利用率:标记清除=标记清除压缩>复制算法
5、JMM(java Memory Model)
- JMM就对应于类似于MSI、MESI、MOSI、Synapse、Firefly及Dragon Protocol这样的缓存一致性协议,用于定义数据读写的规则(遵守,找到规则)。
JMM就对应于类似于MSI、MESI、MOSI、Synapse、Firefly及Dragon Protocol这样的缓存一致性协议,用于定义数据读写的规则。
JMM定义了线程和主内存之间的抽象关系:线程之间的共享变量存储在主内存(Main Memory)中,每个线程都有一个私有的本地内存(Local Memory)
解决共享对象的可见性问题:volilate