JVM
JVM的位置?
在操作系统的下一层和软件并列,在其中运行java程序
JVM的体系结构?
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8zUhOVSc-1592361244885)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20200615095908414.png)]
类加载器
-
作用:加载class文件~
虚拟机自带加载器
启动类(根)加载器 rt.jar
扩展类加载器 /jre/lib/ext/
应用程序(系统)加载器
双亲委派机制:
APP----EXT-----Root(最终执行)
- 类加载器收到了类加载的请求
- 将这个请求向上委托给父类加载器,一直向上委托,直到启动类(boot)加载类
- 启动加载器检查是否加载当前这个类,能加载就结束,不能加载抛出异常,通知自类加载器
- 重复步骤
沙箱安全机制
沙箱机制就是将java代码限定在JVM中运行,并且严格限制代码对本地资源访问,保证代码的有效隔离,防止对本地资源破坏。
基本组件:
- 字节码校验器:确保Java类遵循语言规范,实现内存保护,不是所有的类都会经过校验,比如核心类。
- 类加载器
- 防止恶意代码去干涉善意的代码:双亲委派机制
- 守护好了类库边界
- 将代码归入保护欲,确定代码能进行哪些操作
Native,方法区
凡是带了native关键字,就是表明java作用范围到达不了,回去调用c语言的库
会进入本地方法栈,调用本地方法接口JNI(java native interface),加载本地方法库
JNI扩展java的使用,融合不同的语言
应用: 驱动打印机,管理系统,等等
PC寄存器:
每个线程都有程序计数器,是线程私有的,就是一个指针,指向下一条指令。
方法区:
方法区是被所有线程共享,所有的定义的方法的信息都保存在这个区域,此区域属于共享区域
静态变量,final,Class模板,运行的常量池都在方法区,但是实例变量在堆中,和方法区无关。
栈
程序= 数据结构+算法
先进后出,后进先出
队列(FIFO)
相互递归:就是栈溢出
栈:栈主管程序运行,和线程同生命周期,线程结束,栈释放,不存在垃圾回收。
栈:八大基本类型,对象引用,实例的方法
程序正在执行的方法一定在栈顶
栈 +堆+方法区交互关系:
三种JVM
sun公司:hotspot
BEA JRockit
IBM j9VM
堆
一个 JVM只有一个堆内存,堆内存大小可以调节
堆中有:类,方法,常量,变量,引用类的真实实例。
堆内存分为:
- 新生区 (Eden space),(幸存0区)(幸存1区)
- 养老区
- 永久区存储区(元空间)
GC垃圾回收主要是对伊甸园区和养老区
假设内存满了出现OOM,堆内存不够
新生区:诞生,成长,甚至死亡
伊甸园区:所有的对象诞生的地方
永久区:
这个区域常驻内存,用来存放jdk自身携带的class对象,存储java运行的一些环境或者类信息,不存在啊垃圾回收,关闭虚拟机会释放此空间。
这个区域一般不会oom,除了(一个启动类加载了大量第三方jar包,Tomcat部署太多的应用,或者生成很多的反射类会出现内存溢出)
在JDK1.8后方法区放在了元空间中
解决OOM:
- 尝试扩大内存看结果
- 分析内存,看一下是哪个地方出现了问题
直接看到第几行出错,内存快照分析,MAT(eclipse),JProfiler:分析Dump内存文件,快速定位内存泄露。获得堆得数据,获得大的对象
Dump命令:-Xms1m -Xmx8m -XX:+HeapDempOnOutOfMemeryError
1m:代表一兆,
-Xms:设置初始化内存大小 默认是1/64
-Xmx:设置最大分配内存 默认是1/4
-XX:+PrintGcDetails:垃圾回收信息
-XX:+HeapDempOnOutOfMemeryError ///oom Dump
GC
垃圾回收
JVM进行垃圾回收是,主要对三个区域进行回收,新生区,幸存区,老年区,但并不是统一回收,回收主要是新生区。
GC主要有两类:轻GC和重GC(全局GC)
轻GC:主要作用于新生代和偶尔的幸存区
重GC:新生区,幸存区,老年区
幸存区(from to)交替
GC 有那些算法:
-
引用计数法:
为每个对象计算,所以会生成很多计数器,计数器为0 的消除对象,本身不高效。
-
标记清除法
对存活的对象进行一次标记,第二次,将没有标记的对象清除
优点:不需要额外的空间。对比复制算法
缺点:两次扫描,浪费时间,会产生内存碎片
- 标记压缩法
堆清除进行优化:压缩,防止内存锁片,多了移动成本
- 复制算法
对于GC每次GC都会将存活的对象从伊甸园区转到幸存区,一旦伊甸园区被GC,就会成空。
对于被转来的对象到from还是to区,哪个区域是空的就是to区,转到的区域就是from区
对于每一次GC都会清理幸存区,但是因为有from和to ,from 会把存活的对象复制交给to,伊甸园区也会将新的存活的对象赋值给to ,然后身份交替 to变成from from变成to。to 一定有一个是空的。所以如果一个 对象经历15次就会转到养老区。-XX:MaxTenuringThreshold 多少次进入老年区。
好处:没有内存的碎片
坏处:浪费了内存空间,多了一半to 空间是空的。
复制对象最佳使用:对象幸存率小的时候~~~~~新生区使用
总结
内存效率:复制算法>标记清除>标记压缩(时间复杂度)
内存整齐度:复制算法=标记压缩>标记清除
内存利用率:标记压缩=标记清除>复制算法
没有最好的算法,只有最合适的算法
。GC算法::
年轻代:存活率低:复制算法
老年代:区域大存活率高,标记清除+标记压缩实现
JMM java Memory Model
java内存模型
并发编程等等,最后在看