栈和堆

1、栈

为什么main()先执行,最后结束

栈:栈内存,主管程序的运行,生命周期和线程同步

线程结束,栈内存也就是释放,对于栈来说,不存在垃圾回收问题

一旦现场结束,栈就over!

栈:8大基本类型+对象引用+实例的方法

栈运行原理:栈帧,程序运行的方法一定是在栈顶

栈满了就是StackOverflowError

 

2、堆(HotSpot)

Heap,一个JVM,只有一个堆内存,堆内存大小是可以调节的

类加载器读取了类文件后,一般会把什么东西放入堆中,类、方法、常量、变量~,保存所有的引用类型的真实对象

堆内存中还细分为三个区域

  • 新生区(伊甸园区)Eden Space:
    • 类:一个类诞生和成长的地方,甚至死亡;
    • 伊甸园区,所有的对象都是在伊甸园区new出来的
    • 幸存者区,0和1,
  • 养老区
  • 永久区:元空间(1.8)、方法区,这个区域是常驻内存的,用来存放jdk自身携带的Class对象。Interface元数据,存储的是java运行时的一些环境或类信息~,这个区域不存在垃圾回收。关闭jvm就会释放这个区域的内存~
    • 1.8之後,常量池在云空间

GC垃圾回收,主要是在伊甸园去和养老区

假设内存满了,OOM,堆内存不够,OutOfMemoryError

 

 

 

  真哩:经过研究,99%的对象都是临时对象。

3、调优

默认情况下:分配的总内存是电脑的1/4,而初始化内存:1/16

OOM:

1、尝试扩大堆内存,看结果

2、分析内存,看哪个地方出现问题

 

4、GC算法

垃圾回收算法理解:https://zhuanlan.zhihu.com/p/297965515

JVM在进行GC时,并不是对这三个区域统一回收,大部分时候,回收的都是新生代~

  • 伊甸园区
  • 幸存区(from,to)
  • 老年区

1) 引用计数法

 

 

2) 复制算法

 

 

 

 

 

 3) 标记清除算法

对用过的对象进行标记,扫码所有的对象,未标记的对象进行清理

4)标记压缩算法

在标记清除算法基础上增加压缩内存操作,移动标记的对象到内存的一端

 

 总结

5、分代收集算法

  根据对象存活周期的不同将内存划分为几块,入JVM中的新生代,老年代,永久代,这样就可以根据各年代特点分别采用最适当的GC算法

  1.1在新生代使用复制算法: 因为新生代每次垃圾收集都能发现大批的对象已死,只有少量存活,因此选用复制算法,只需要付出少量存活对象的复制成本就可以完成收集.

  1.2在老年代使用标记整理算法:因为对象存活率高,没有额外空间对它进行分配担保,就必须采用”标记-清理“或者”标记-整理“算法来进行回收,不必进行内存复制,直接腾出空闲内存

 

posted @ 2022-04-01 18:11  zhaoyanhao  阅读(90)  评论(0编辑  收藏  举报