自学内容网 自学内容网

JVM内存结构

JVM虚拟机拿到内存后对内存进行割分

栈、局部方法栈和程序计数器是线程私有的

堆、方法区是线程公有的

栈: 主要用于存储方法的局部变量基本数据类型

堆: 存储Java应用程序中创建的对象和数组,因为是公有的(全局共享),所有线程都可以访问它,因此它需要有效的垃圾回收机制来管理内存的分配和释放。也就是GC

本地方法栈:用来存储c++(等其它语言)的native方法栈区

程序计数器:指向程序当前运行的位置,就相当于存档

方法区:存放静态变量,类加载器等全局的信息(数据全局共享)

代码举例1:

func1中的方法会在运行结束后就从栈中按先进先出的方式删除

所以最后就剩a=10,打印出来的结果也就是10

代码举例2:

下面这段代码也同样,a,b,p对象都放在栈中,p存储的是对象的地址

因为name是String引用类型,所以还会在栈中再开辟一块空间存放

当方法结束后栈中会删除这些数据,但是堆中不会删除,有些对象也会被引用,所以就导致堆中可能要爆

GC过程:

GCRoot:

  1. 被栈直接或间接引用
  2. 本地方法栈直接或间接引用
  3. 被方法区静态或常量直接或间接引用的(全局)

GCroot符合这三条中的其中之一的都不能被删除

三种清理方法:

1.标记——清理: 被标记上的就清理掉

缺点:内存碎片

2.标记——整理: 清理掉被标记的并且把空间都集中(把其他对象都往前挪)

缺点:代价大,每次删除都要挪全部的对象

3.复制: 将整个内存一分为二,将不需要删除的复制到2区,这样就可以避免空间碎片

缺点:2倍内存

实际GC过程:

年轻代分为三个区:

S区:survive区幸存者区,一个To区,一个From区,(谁是空的谁就是To区)

E区:伊甸园,生命开始的地方;新new的对象都放在E区

当对象要将E区填满的时候就会触发GC

过程:

年轻代:

当E区快满的时候,标记的所有对象都会转移到S1区,同时系统会把S2区和E区看为一个整体将里面的东西全部删除。下次E区快满时,将标记的对象复制到S2区中,将S1和E区的对象删除,就这样循环往复。

E+S1复制到S2

E+S2复制到S1

E+S1复制到S2

老年区:主要存放大对象和age>=6的对象

每次对新生代中对象复制的时候都会进行标记,如果幸存年龄就会+1,年龄大于等于6时就会进入老年代。(这意味着这个对象可能在以后100次200次GC中都能存活下来)

当老年代中对象满了:

就会触发第一种或第二种清理方式:

1.标记——清理

2.标记——整理


原文地址:https://blog.csdn.net/qq_62859013/article/details/142378085

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!