JVM
内存模型
共享区(方法区,堆内存)+ 私有区(虚拟机栈,本地方法栈,程序计数器)
堆(运行时常量池) | new的对象就会放在堆中 (-Xmx -Xms) |
---|---|
方法区 | 加载好的类放在方法区,静态成员 |
栈(JVM栈和本地方法栈) | 局部变量 |
程序计数器 | 存储的是地址描述的是当前线程接下来要执行的指令在什么地方 |
局部变量:在方法内的,如参数,方法体内声明的变量 ,栈中
全局变量:直接在类中,属于类的属性,可以在本类的所有实例方法中访问(非static修饰的),堆中
注意:一个进程中存在多个线程,每个线程中都存在自己的栈和程序程序计数器,一个进程中共用一个堆和一个方法区。
判断一个变量是在堆上还是在栈上,和这个变量是基础类型还是引用类型没有关系,和这个变量是局部变量、静态变量还是成员变量有关。
线程、主内存、工作内存关系图
JVM会为每一个thread开辟一块自己的工作空间,在我们操作变量时是从主内存拿到变量的一个副本,然后对副本进行操作后再刷新到主内存中这么一个总体的流程。
三种基础垃圾回收算法
复制收集算法:把内存分成两块,每次只使用其中的一块,把正在使用存活的对象复制到不使用的内存里,再清理掉正在使用的这块内存,接着交换两块内存的角色,等待下一次回收
标记 - 清理算法:先标记垃圾,再清除。缺点,标记清除后会产生大量不连续的内存碎片,这是垃圾收集算法中最基础的
标记 - 整理算法:先标记在整理,把所有的存活对象都压缩到内存的一端,最后在清理掉边界之外的所有空间,所以不会产生内存碎片,提高了内存的利用率,这种算法适用于老年代
分代收集:现在的虚拟机垃圾收集大多采用这种方式,它根据对象的生存周期,将堆分为新生代和老年代
新生代中,由于对象生存期短,每次回收都会有大量对象死去,那么这时就采用复制算法
老年代里的对象存活率较高,没有额外的空间进行分配担保,所以可以使用标记-整理 或者 标记-清除。
调优步骤
1.监控GC的状态
使用各种JVM工具(jdk自带 jconsole 等),查看当前日志,分析当前JVM参数设置,并且分析当前堆内存快照和gc日志,根据实际的各区域内存划分和GC执行时间,觉得是否进行优化。
2.生成堆的dump文件
3.分析dump文件
堆栈区别
- 功能方面:堆是用来存放对象的,栈是用来执行程序的。
- 共享性:堆是线程共享的,栈是线程私有的。
- 空间大小:堆大小远远大于栈。
值引用&对象引用
值引用 | 对象引用 | |
---|---|---|
范围 | 八大基本数据类型 | 对象 |
存放地址 | 栈 | 栈(=对象地址)、堆(对象) |
入参变化情况 | 不会改变原来的值 | 可以改变原对象的属性值,不能改变原对象的引用地址 |
原因 | 作为入参的方法会重新开辟新的栈,数据完全复制一份作为参数 | 新的栈中参数复制了原来的引用地址,如果不改变引用地址,就可修改原来对象的属性 |
日夜颠倒头发少 ,单纯好骗恋爱脑 ,会背九九乘法表 ,下雨只会往家跑 ,搭讪只会说你好 ---- 2050781802@qq.com