设为首页 加入收藏

TOP

JVM总结(一)
2023-07-25 21:41:17 】 浏览:68
Tags:JVM 总结

JVM总结

1. 内存结构

image-20230225154307114

线程私有区

程序计算器

  • 作用:是一块较小的内存空间,存储的是当前线程所执行的字节码文件的序号
  • 特点:线程私有,不会出现内存空间溢出

虚拟机栈

虚拟机栈是管理JAVA方法执行的内存模型,每个方法执行时都会创建一个当前栈桢,在当前栈桢里面存储方法的局部变量表,操作数栈,动态链接方法,返回值,返回地址等信息,栈大小决定了方法调用的可达深度(递归多少层,嵌套调用多少层其他方法,在idea中,-Xss参数可以设置虚拟机栈的大小)

  • 是线程私有的
  • 局部变量表存放了编译期可知的所有基本数据类型(byte,short,int,long,float,double,boolean,char),以及对象引用
  • 栈太小或者方法调用过深都将抛出StackOverFlowError异常

本地方法栈

为本地语言服务的栈,Native方法服务

线程共享区

堆内存

存放对象实例的区域,对象,数组,以及常量池(从java7开始常量池也会使用堆内存)

堆内存从GC角度可以分为:新生类(Eden区,From Survision区和To Survision区),老年代,永久代(在Java8的时候被移除了)

特点:是线程贡献,需要考虑线程安全问题,同时会产生内存溢出问题

-Xms 设置最小堆内存大小(不能小于1024K)

-Xmx:设置最大堆内存大小(不能小于1024K)

方法区

用于存储已被虚拟机加载的类信息,常量,静态变量,即时编译器编译后代码等数据

image-20230227220649797

特点:

  • 是一块线程共享的内存区域
  • 方法区的大小决定了系统可以保存多少个类,如果系统定义了太多的类,导致方法区溢出,虚拟机同样会抛出内存溢出的错误
  • 现在说的方法区一般是指元数据区(元空间Metaspace,java8的时候添加的),如果不指定大小,默认情况下,虚拟机会耗尽系统的可用内存

堆栈的区别

  • 存储的东西不同,栈内存存储局部变量和方法调用,而堆内存存储对象,包括成员变量,局部变量,还有类变量
  • 共享不同,栈内存是线程私有的,堆内存是所有线程共有的
  • 异常错误不同:栈空间不足:java.lang.StackOverFlowError,堆空间不足:java.lang.OutOfMemoryError。
  • 大小不同,栈空间小于堆空间

获取堆内存数据

java.lang.Runtime类中包含了与内存先关的方法

获取剩余空间的的字节数:Runtime.freeMemory()

获取总内存的字节数:Runtime.totalMenory()

2. 垃圾回收

垃圾回收机制

在Java中,程序员不需要显示的去释放一个对象的内存,而是由虚拟机自动去执行,在JVM中,有一个垃圾回收线程,他是低优先级的,在正常情况下是不会执行的,只有在虚拟机空闲或者在堆内存不足时才会触发执行,扫描那些被视为垃圾的对象,将他们添加到回收的集合中进行回收,也可以进行手动回收,通过System.gc(),通知GC运行

垃圾回收算法

  • 标记清除法

    标记出所有需要回收的对象,在标记完成后,统一回收的被标记的对象

    优点:速度比较快

    缺点:会产生内存碎片,碎片过多,仍会使得连续空间变少

  • 标记整理

    标记出所有需要回收的对象,在标记完成后统一进行整理,将存活对象进行一端移动,减少内存碎片,效率相对较低

    优点:无内存碎片

    缺点:效率较低

  • 复制算法

    开辟两份大小相等的空间,一份空间始终空着,垃圾回收时将存活对象拷贝进空闲时间

    优点:无内存碎片

    缺点:占用空间多

  • 分代回收

根据对象的存活周期不同,将对象划分为几块,比如堆内存的新生代和老年代,然后根据各个年代的特点采用最合适的算法进行回收;

新生代对象的存活时间比较短,因此使用的是复制算法,老年代对象存活的时间比较长,因此使用的是标记清除或者标记整理

分代垃圾回收的过程

分代垃圾回收器分两个区,新生代和老年代,新生代默认占1/3,老年代占2/3

新生代使用复制算法,新生代里面又分3个区(Eden,To Survivor, From Survicior)默认占比是8:1:1,当Eden区满了之后就会触发第一次MinorGC,将Eden区和From区存活的对象复制到To Survivor区域,然后to Survivor区域和From Survivor互换,原来的To Servivor区域成为下一次的From Survivor区域,然后清空Eden和From Survivor区中的对象,From中的对象每经过一次MinorGC,他的年龄值就会加1,达到15的移动到老年代,这里使用了复制算法,老年代满了或者是超过了临界值则会触发完全垃圾回收

判断一个对象是否为垃圾

引用计数法

堆中每个对象实例都有一个引用计数,当一个对象被创建的时候,且将这个对象实例分配给一个变量,该变量计数设置为1,当任何其他变量被赋值为这个对象的引用时,计数加1,但当一个对象实例的某个引用超过了生命周期,或者被设置为一个新值时,这个对象实例的引用计数将会减1,任何引用计数为0的对象都是可以被当做垃圾收集的对象,也就是一个垃圾,引用计数法容易产生循环引用的问题,如果两个对象相互引用,那么他们的引用就会一直存在,导致一直无法回收,为了解决这个问题,下面引入了可达性分析法

可达性分析算法

可达性分析算法又叫做根搜索法,就是通过一系列的称之为“GC Roots”的对象作为起始点,从这些节点开始向下搜索,搜索走过的路径被称为(Reference Chain)影响链,当一个对象到GC Roots没有任何链相连时(即从 GC Roots节点到该节点是不可达的),则这个对象就是可以被当做垃圾收集的对象,也就是一个垃圾

可以被作为GC Roots的对象

  • 虚拟机栈中引用的对象
  • 方法区静态成员的引用对象
  • 方法区常量的引用对象
  • 本地方法栈引用的对象

引用类型

  • 强引用

    默认声明的就是强引用,只要强引用存在,垃圾回收器就永远不会回收该对象,哪怕内存不足时也不会去回收,所以强引用是造成Java内存泄漏的主要原因,如果想回收某个对象可以将值赋值为null,切断强引用关系

  • 软引用:一些非必需但是仍有用的对象,通过SoftReference实现,在内存足够的时候,软引用对象不会回收,在内存不足时则会回收,当回收了软引用对象内存还是不足时,会抛出内存溢出异常

  • 弱引用:比软引用的引用强度更低一些,通过WeakReference实现,无论内存是否足够,JVM都会被进行垃圾回收

  • 虚引用:最弱的引用关系,通过PhantomReference类实现,每次垃圾回收都会被回收,主要用于跟踪对象的垃圾回收状态,虚引用的对象始终返回一个null,虚引用对象始终和引用队列一起使用,当一个对象还存在虚引用时,会被加入到引用队列中

首页 上一页 1 2 3 下一页 尾页 1/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇一个更适合Java初学者的轻量级开.. 下一篇面试官:怎么删除 HashMap 中的元..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目