java基础-java虚拟机-JVM垃圾回收机制-解决内存泄漏和内存溢出-底层原理

一、JVM垃圾回收机制的算法

1.1、Mark-Sweep(标记-清除)算法
是最基础的垃圾回收算法,其他算法都是基于这种思想。标记-清除算法分为“标记”,“清除”两个阶段:首先标记出需要回收的对象,标记完成后统一清除对象。
缺点:
1:标记和清除的效率不高。
2:标记之后会产生大量不连续的内存碎片。
在这里插入图片描述

1.2、Copying(复制)算法
将可用内存分为两块,每次只用其中的一块,当这块内存用完以后,将还存活的对象复制到另一块上面,然后再把已经使用的内存空间一次清理掉。
优点:
1:不会产生内存碎片。
2:只要移动堆顶的指针,按顺序分配内存即可,实现简单,运行高效。
缺点:内存缩小为原来的一半
在这里插入图片描述

1.3、Mark-Compact(标记-整理)算法
标记操作和”标记-清除“算法一样,后续操作变成不直接清理对象,而是在清理无用对象的时候完成让所有存活的对象都像一端移动,并更新对象的指针。
优点:不会产生内存碎片
缺点:在“标记-清除”基础上还要进行对象的移动,成本相对较高
在这里插入图片描述

1.4、Generational Collection(分代收集)算法(重点)
是目前大部分JVM的垃圾收集器采用的算法。它的核心思想是根据对象存活的生命周期将内存划分为若干个不同的区域。一般情况下将堆区划分为老年代(Tenured Generation)和新生代(Young Generation),老年代的特点是每次垃圾收集时只有少量对象需要被回收,而新生代的特点是每次垃圾回收时都有大量的对象需要被回收,那么就可以根据不同代的特点采取最适合的收集算法。
目前大部分垃圾收集器对于新生代都采取Copying算法,因为新生代中每次垃圾回收都要回收大部分对象,也就是说需要复制的操作次数较少,但是实际中并不是按照1:1的比例来划分新生代的空间的,一般来说是将新生代划分为一块较大的Eden空间和两块较小的Survivor空间,每次使用Eden空间和其中的一块Survivor空间,当进行回收时,将Eden和Survivor中还存活的对象复制到另一块Survivor空间中,然后清理掉Eden和刚才使用过的Survivor空间。
而由于老年代的特点是每次回收都只回收少量对象,一般使用的是Mark-Compact算法。
在这里插入图片描述

注意,在堆区之外还有一个代就是永久代(Permanet Generation),它用来存储class类、常量、方法描述等。对永久代的回收主要回收两部分内容:废弃常量和无用的类。

在这里插入图片描述

二、了解JVM内存模型

在这里插入图片描述

1、方法区:也称“永久代”,“非堆”,用于储存虚拟机加载的类信息,常量,静态变量,是各个线程共享的内存区域。
运行时常量池:方法区的一部分,Class文件中除了有类的版本,字段,方法,接口等描述信息外,还有一项信息就是常量池,用于存放编译器生成的各种符号引用,这部分内容将在类加载后放到方法区的运行时常量池中。

2、虚拟机栈:描述的是java方法执行的内存模型,每个方法被执行的时候,都会创建一个“栈帧”用于存储局部变量(包括参数),操作栈,方法出口等信息。每个方法被调用到执行完成的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。生命周期与线程相同,是线程私有的。

局部变量表:存放八种基本类型,对象引用,其中64位长度的long和double类型的数据会占用两个局部变量的空间,其余数据类型只占一个。局部变量表是在编译时完成分配的,当进入一个方法时,这个方法需要在栈帧中分配多大的局部变量是完全确定的,在运行期间不再改变。

3、本地方法栈:与虚拟机栈基本类似,为Native方法(本地方法)服务。

4、堆:也叫Java堆,GC堆。是JVM中所管理的内存中最大的一块内存区域,是线程共享的,在JVM启动时创建。存放了对象的实例及数组(所有new的对象)。

三、JDK可视化监控工具

JConsole 在bin目录下,自动后自动搜索jvm进程,不需要指定。
有概述,内存,线程,类,VM摘要和Mbean六个页签。
概述:显示有关JVM的监测值
内存: 显示内存使用信息
注意垃圾回收次数、时间、以及partial GC和full GC
线程: 显示线程使用信息
类: 显示类装载信息
VM摘要:显示java VM信息
MBeans: 显示 MBeans

四、内存泄漏和内存溢出

先有内存泄漏:该被回收的内存或者对象,无法回收导致内存一直被占用,才会有内存溢出:内存不够,导致程序崩溃。

解决方法:
1.写出高效代码
(1)尽量不要再循环中使用try…catch,new对象等;
(2)把频繁使用的短命对象缓存起来;
(3)尽可能是用栈内变量(方法内局部变量);
(4)不要用异常来控制代码流程;
(5)用线程池,连接池,不要自己创建;
(6)学会读java核心API源代码;

2.修改内存大小:
在这里插入图片描述

ps:以上是个人对JVM的一些见解,如有不对的地方还请指正,我会及时修改,一起讨论,学习。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
JVMJava虚拟机内存模型和垃圾回收Java程序重要的概念。JVM内存模型定义了Java程序在运行时所使用的内存结构,而垃圾回收是一种自动化的内存管理制,用于回收不再使用的对象以释放内存空间。 JVM内存模型主要包括以下几个部分: 1. 堆(Heap):堆是JVM最大的一块内存区域,用于存储对象实例。在堆分配的内存垃圾回收自动管理。 2. 方法区(Method Area):方法区用于存储类的信息、常量、静态变量等数据。在JDK 8及之前的版本,方法区被实现为永久代(Permanent Generation),而在JDK 8之后,被改为元空间(Metaspace)。 3. 虚拟机栈(VM Stack):每个线程在运行时都会创建一个虚拟机栈,用于存储局部变量、方法调用和返回信息等。每个方法在执行时都会创建一个栈帧(Stack Frame),栈帧包含了方法的局部变量表、操作数栈、动态链接、返回地址等信息。 4. 本地方法栈(Native Method Stack):本地方法栈与虚拟机栈类似,但用于执行本地方法(Native Method)。 垃圾回收JVM的一项重要功能,它负责自动回收不再使用的内存JVM垃圾回收器会定期扫描堆的对象,标记出不再被引用的对象,并将其回收释放。垃圾回收可以有效地避免内存泄漏内存溢出的问题,提高程序的性能和稳定性。 JVM内存模型和垃圾回收Java程序员需要了解和理解的重要概念,它们直接影响到Java程序的性能和内存使用情况。合理地管理内存和优化垃圾回收对于编写高效、稳定的Java程序至关重要。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值