Java的内存分配与垃圾回收

jvm内存结构分为五大区域:程序计数器、虚拟机栈、本地方法栈、堆区、方法区。

各个区域特点如下

堆区: 
(1).存储的全部是对象,每个对象都包含一个与之对应的class的信息(class的目的是得到操作指令)。
(2).jvm只有一个堆区(heap),且被所有线程共享,堆中不存放基本类型和对象引用,只存放对象本身和数组本身。
(3).通常可分为两个区块新生代老年代。更新一点新生代可分为Eden区,主要放新创建对象,From survivor 和 To survivor 保存 gc 后幸存下的对象,默认情况下各自占比 8:1:1。

栈区: 
(1).每个线程包含一个栈区,栈中只保存基础数据类型本身和自定义对象的引用。
(2).每个栈中的数据(原始类型和对象引用)都是私有的,其他栈不能访问。
(3).栈分为3个部分:基本类型变量区、执行环境上下文、操作指令区(存放操作指令)。

方法区: 
(1).被所有的线程共享,方法区包含所有的class(class是指类的原始代码,要创建一个类的对象,首先要把该类的代码加载到方法区中,并且初始化)和static变量。 
(2).方法区中包含的都是在整个程序中永远唯一的元素,如class,static变量。
(3).习惯被称为永久代

程序计数器:
是当前线程所执行的行号指示器,跳转指令等都依赖这个完成,线程私有。

垃圾回收的目的和原理

目的:
以自动监测对象是否超过作用域从而达到自动回收内存的目的。垃圾回收可以有效的防止内存泄露,有效的使用可以使用的内存。

原理:
GC采用有向图的方式记录和管理堆(heap)中的所有对象。通过这种方式确定哪些对象是"可达的",哪些对象是"不可达的"。当GC确定一些对象为"不可达"时,GC就有责任回收这些内存空间。
垃圾回收器通常是作为一个单独的低优先级的线程运行,不可预知的情况下对内存堆中已经死亡的或者长时间没有使用的对象进行清除和回收,程序员不能实时的调用垃圾回收器对某个对象或所有对象进行垃圾回收。

垃圾回收概述

上文提到的jvm内存区域中,其中虚拟机栈、本地方法栈与程序计数器这3个区域随线程而生、随线程而灭,因此就不需要考虑过多内存垃圾回收问题。GC的重点在方法区与堆区,这部分内存的分配和回收是动态的。

一.对象是否存活的判断方法:

(1)引用计数法:
难以解决对象之间相互引用问题,主流的JVM都没有采用这一方法。

(2)可达性分析法:
通过一系列被称为“GC Roots”的点作为起始点,从这些节点开始向下搜索,搜索的路径称为引用链,当一个对象到GC Roots不可达的时候,则证明此对象是可回收的。

二.垃圾回收算法:

(1)    标记清除法
标记清除法有两个过程,一是标记过程,即判定需要回收的对象的过程,通过可达性分析便可分析出来。二是清除阶段,这个阶段就是对标记了的对象进行回收。缺点:一是标记和清除的效率都不是很高。二是执行完GC后会造成大量的内存碎片,如果以后分配大内存对象的的时候无法找到足够大的连续内存,就会频繁触发GC。

(2)复制算法
将可用内存平均划分为两块,每次只使用其中一块。当这一块用完了,就将还存活的对象复制到另一块,然后再把已使用的内存空间一次清理掉。这样每次GC的时候都直接回收半个内存空间的大小,不必考虑碎片问题。但这种方法带来的代价也不小,牺牲了一半的存储空间。

(3)标记整理法
标记整理法的执行过成分为3步:1.用与“标记清除法”一样的操作标记存活的对象;2.将被标记的对象全部移动到内存的某一端;3.清除边界以外部分的内存。

(4)分代回收法
在分代回收算法中,会根据对象的存活周期,将内存划分为几块,一般是新生代(Young Generation)、老年代(Old Generation)、永久代(Permanent Generation)。这样就可以根据不同内存区域的特点执行采用不同的回收算法。像新生代这种经常有大批对象死去的区域,就适合用复制算法。而对于老年代这种对象生存周期较长和永久代这种内存存活率较高,又没有其他担保空间的地方就用标记清除法或标记整理法就行了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值