JVM
2020-07-03 12:05:24 0 举报
AI智能生成
JVM
作者其他创作
大纲/内容
01 JVM的位置
JAVA程序跑在JVM上面,JRE-JVM,在操作系统之上(windows,linux),最底下是硬件体系
02 JVM的体系结构
见图谱
jvm调优说的是“方法区”和“堆”,而“栈”“本地方法栈”“程序计数器”不存在垃圾回收一事
虚拟机试图使用最大内存为电脑内存的1/4,而JVM初始化内存为1/64
03 类加载器
作用:加载类文件,引用在栈中,具体实例在堆中
虚拟器自带的3种类加载器
三类
启动类(根)加载器
扩展类加载器
应用程序加载器(系统类加载器)
04 双亲委派机制
双亲委派机制是一个类加载器需要加载类,那么首先会把这个类请求委派给父类加载器去完成,每一层如此,一直递归到顶层,当父类加载器无法完成这个请求时,子类才会尝试去加载
见图谱
安全
05 沙箱安全机制
java安全模型核心
沙箱:限制程序的运行时环境
域Domain概念
将java代码限定在虚拟机特定的运行范围内,严格限制代码对本地系统资源的访问,这样措施保证对代码的有效隔离,防止对本地系统的破坏
06 native关键字
调用底层C,C++语言库
native->JNI->本地方法接口->本地方法库
本地方法栈
一般用的不多,硬件开发用的多
07 PC程序计数器
pc寄存器
程序计数器Program Counter Register
每个线程都有一个程序计数器,线程私有,就是一个指针,指向方法区中的方法字节码,(用来存储指向下一条指令的地址,也即即将要执行的指令代码),在执行引擎读取下一条指令
非常狭小空间
可以忽略不计
08 方法区
方法区,所有线程共享
静态变量,常量,类信息(构造方法,接口定义...),运行时的常量池,但实例在堆内存中,与方法区无关
09 栈
栈:先进后出,后进先出;队列:先进先出,后进后出;
线程结束,栈内存释放
主管程序的运行
存放基本类型,实例方法,对象引用...
栈帧:父帧子帧,每一个在执行的方法都会产生栈帧
栈满,报错:StackOverflowError
10 三种JVM
SUN公司
HotSpot
学习!!
BEA公司
JRocket
IBM公司
J9
11 堆
一个JVM只有一个堆内存
保存我们所有引用类型的真实对象
3个区域
新生区(伊甸园)
所有的对象都new在了伊甸园区,从中出生
养老区
老年区
从新生区(幸存0幸存1)中顺下来的,干不掉杀不死
永久区
此区域不存在垃圾回收,但是也会崩(eg:启动了大量第三方jar包等)
永久区是一个常驻内存区域,用于存放JDK自身所携带的Class Interface的元数据
jdk1.6之前永久代,常量池是在方法区
jdk1.7永久代,慢慢退化,去永久代,常量池在堆中
jdk1.8无永久代,常量池在元空间
关闭虚拟机就会释放这块内存
gc垃圾回收主要针对伊甸园区和养老区
12 堆内存调优
报OOM时
尝试扩大堆内存空间,看结果(调参试试看)
分析内存,看一下哪个地方出现问题(专业工具)
内存快照分析工具,MAT(eclipse),Jpofiler
作用:分析DumpN内存文件,快速定位内存泄露,获得堆中的数据,获取大的对象
使用JPofiler工具分析OOM原因
虚拟机基本配置参数
-Xms 设置java程序启动时初始堆大小
初始化内存大小
-Xmx 设置java程序能获得的最大堆大小
最大内存大小
-XX:+HeapDumpOnOutOfMemoryError,使用该参数可以在内存溢出时导出整个堆信息
-XX:HeapDumpPath ,可以设置导出堆的存放路径。
-XX:+PrintGCDetails 打印GC垃圾回收信息
举例
-Xms1m -Xmx1m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=d:/Test03.dump
13 GC
垃圾回收为自动,手动只能提醒
GC作用于堆+方法区
GC大部分时候针对新生代
轻GC
普通GC
重GC
全局GC
GC算法
标记清除算法
扫描对象,对活着的对象进行标记,对没有标记的对象进行清除
优点:不需要额外空间,优于复制算法
缺点:两次扫描,浪费时间,会存在内存碎片
标记压缩算法
再优化,压缩:防止碎片的产生
方法:再扫描,向一端移动存活的对象,多了一个移动成本
标记清除压缩算法
先标记清除几次再进行压缩,等碎片多了之后
复制算法
该算法将内存平均分成两部分,然后每次只使用其中的一部分,当这部分内存满的时候,将内存中所有存活的对象复制到另一个内存中,然后将之前的内存清空,只使用这部分内存,循环下去
幸存区01,from..to...,0和1相互不断交换,进行gc进行复制算法
若一直没死进入到养老区
优点:实现简单,不产生内存碎片
缺点:浪费一半内存空间
引用计数算法
每个对象一个计数器,一般不用,因为计数器有消耗,用过多次的不删,0次的就删除了
引用出现+1引用删除-1
总结
内存效率
时间复杂度
复制>标记清除>标记压缩
内存整齐度
复制算法=标记压缩>标记清除
内存利用率
标记压缩=标记清除>复制算法
分代收集算法(JVM调优)
没有最好的算法,只有最合适
年轻代
存活率低,复制算法
老年代
存活率高
标记清除与标记压缩混合实现
14 JMM
Java Memory Model ;Java内存模型
抽象概念,理论
定义了线程工作内存和主内存之间的抽象关系
线程之间的共享变量存储在主内存中
MAIN MEMORY
每个线程都有一个私有的本地内存
LOCAL MEMORY
与并发相关
15 OOM的种类和原因
java.lang.OutOfMemoryError
内存泄漏(memory leak)是指程序中己动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。
内存溢出 (out of memory)是指程序申请内存时,没有足够的内存供申请者使用,说白就是内存不够用,此时就会报错OOM,即所谓的内存溢出。
OOM种类和原因
java堆溢出
见下!
既然堆是存放实例对象的,那就无限创建实例对象。
虚拟机栈溢出
虚拟机栈描述的是java方法执行的内存模型,每个方法在执行的时候都会创建一个栈帧用于存储局部变量表、操作数栈、动态连接、方法出口等信息。本地方法栈与虚拟机栈的区别是,虚拟机栈为虚拟机执行java方法服务,而本地方法栈则为虚拟机提供native方法服务。
在单线程的操作中,无论是由于栈帧太大,还是虚拟机栈空间太小,当栈空间无法分配时,虚拟机抛出的都是StackOverflowError异常,而不会得到OutOfMemoryError异常。而在多线程环境下,则会抛出OutOfMemoryError异常。
在单线程的操作中,无论是由于栈帧太大,还是虚拟机栈空间太小,当栈空间无法分配时,虚拟机抛出的都是StackOverflowError异常,而不会得到OutOfMemoryError异常。而在多线程环境下,则会抛出OutOfMemoryError异常。
本地方法栈溢出
见上!
方法区和运行时常量池溢出
java堆和方法区:java堆区主要存放对象实例和数组等,方法区保存类信息、常量、静态变量等等。运行时常量池也是方法区的一部分。这两块区域是线程共享的区域,只会抛出OutOfMemoryError。
本机内存直接溢出
NIO有关
NIO(New Input/Output),引入了一种基于通道与缓冲区的 I/O 方式,可使 native 函数库直接分配堆外内存,然后通过一个存储在Java堆中的对象作为这块内存的引用进行操作。这样能在一些场景中显著提高性能,因为避免了在 Java 堆和 Native 堆中来回复制数据。
程序计数器不会溢出!!
0 条评论
下一页