Java有自己的Java内存回收机制制,但为什么还存在

温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!&&|&&
LOFTER精选
网易考拉推荐
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
控制台日志:日志中非常清晰的可以看到,我们分配了一个4M内存大小,直接是分配在了eden space里面。2. 大对象直接进入老生代。参数:-XX:PretenureSizeThreshold(该设置只对Serial和ParNew收集器生效) 可以设置进入老生代的大小限制,我们设置为3M,则大于3M的大对象就直接进入老生代测试代码:控制台日志:上面的日志中,可以清洗看到第一次分配的2M留存在了eden space中,而4M超过了大对象设置的值3M,所以直接进入了老生代tenured generation3. 长期存活的对象进入老年代为了演示方便,我们设置-XX:MaxTenuringThreshold=1(默认15),当在新生代中年龄为1的对象进入老年代。测试代码:控制台日志:我们可以看到在A3处有一次GC,并且a2的7M已经满足-XX:MaxTenuringThreshold=1的要求,所以a2进入老年代,而空出来的空间a3就进入新生代4. 动态对象年龄判定为了使内存分配更加灵活,虚拟机并不要求对象年龄达到MaxTenuringThreshold才晋升老年代如果Survivor区中相同年龄所有对象大小的总和大于Survivor区空间的一半,年龄大于或等于该年龄的对象在Minor GC时将复制至老年代5. 空间分配担保新生代使用复制算法,当Minor GC时如果存活对象过多,无法完全放入Survivor区,就会向老年代借用内存存放对象,以完成Minor GC。在触发Minor GC时,虚拟机会先检测之前GC时租借的老年代内存的平均大小是否大于老年代的剩余内存,如果大于,则将Minor GC变为一次Full GC,如果小于,则查看虚拟机是否允许担保失败,如果允许担保失败,则只执行一次Minor GC,否则也要将Minor GC变为一次Full GC。说白了,新生代放不下就会借用老年代的空间来进行GCJava垃圾收集器:首先我们可以看一张图,下面这张图中列出来新生代和老生代可以用到的垃圾收集器。1. Serial 收集器 串行单线程的串行收集器。它在垃圾收集的时候会暂停其它所有工作线程。直到收集结束。一般在客户端模式下使用。2. ParNew收集器 并行ParNew收集器是Serial的多线程版本。一般运行在Server模式下首先的新生代收集器。如果老年代使用CMS收集器,基本也只能和它进行合作。参数:-XX:+UseConcMarkSweepGC,比较适合web服务的收集器。一般ParNew和CMS组合3. Parallel Scavenge收集器 并行它使用复制算法的收集器,并且是多线程的。该收集器主要目的就是达到一个可控制的吞吐量,说白了就是CPU的利用率。于是该收集器比较适合后端运算比较多的服务。-XX:MaxGCPauseMillis每次年轻代垃圾回收的最长时间(最大暂停时间),收集器尽量保证内存回收时间不大于这个值,应该设置一个合理的值。-XX:GCTimeRatio设置垃圾回收时间占程序运行时间的百分比-XX:+UseAdaptiveSizePolicy&设置此选项后,并行收集器会自动选择年轻代区大小和相应的Survivor区比例,以达到目标系统规定的最低相应时间或者收集频率等,此值建议使用并行收集器时,一直打开.4.Serial Old收集器 串行单线程串行的老生代收集器。5. Parallel Old 收集器 并行使用“标记-整理”的算法。该收集器比较适合和Parallel Scavenge收集器进行组合。-XX:+UseParallelOldGC6. CMS收集器CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器,目前大部分的B/S系统都使用CMS的收集器。一般CMS是老生代收集器,新生代就和PerNew进行组合。CMS收集器基于“标记-清除”的算法。分四个阶段:初始标记,并发标记,重新标记,并发清除CMS收集器的优点:并发收集、低停顿CMS缺点:1. CMS收集器对CPU资源非常敏感。在并发阶段,虽然不会导致用户线程停顿,但是会占用CPU资源而导致引用程序变慢,总吞吐量下降。CMS默认启动的回收线程数是:(CPU数量+3) / 4。2. CMS收集器无法处理浮动垃圾,可能出现“Concurrent Mode Failure“,失败后而导致另一次Full &GC的产生。由于CMS并发清理阶段用户线程还在运行,伴随程序的运行自热会有新的垃圾不断产生,这一部分垃圾出现在标记过程之后,CMS无法在本次收集中处理它们,只好留待下一次GC时将其清理掉。这一部分垃圾称为“浮动垃圾”。也是由于在垃圾收集阶段用户线程还需要运行,即需要预留足够的内存空间给用户线程使用,因此CMS收集器不能像其他收集器那样等到老年代几乎完全被填满了再进行收集,需要预留一部分内存空间提供并发收集时的程序运作使用。在默认设置下,CMS收集器在老年代使用了68%的空间时就会被激活,也可以通过参数-XX:CMSInitiatingOccupancyFraction的值来提供触发百分比,以降低内存回收次数提高性能。要是CMS运行期间预留的内存无法满足程序其他线程需要,就会出现“Concurrent Mode Failure”失败,这时候虚拟机将启动后备预案:临时启用Serial Old收集器来重新进行老年代的垃圾收集,这样停顿时间就很长了。所以说参数-XX:CMSInitiatingOccupancyFraction设置的过高将会很容易导致“Concurrent Mode Failure”失败,性能反而降低。3. CMS是基于“标记-清除”算法实现的收集器,使用“标记-清除”算法收集后,会产生大量碎片。空间碎片太多时,将会给对象分配带来很多麻烦,比如说大对象,内存空间找不到连续的空间来分配不得不提前触发一次Full &GC。为了解决这个问题,CMS收集器提供了一个-XX:UseCMSCompactAtFullCollection开关参数,用于在Full &GC之后增加一个碎片整理过程,还可通过-XX:CMSFullGCBeforeCompaction参数设置执行多少次不压缩的Full &GC之后,跟着来一次碎片整理过程。
阅读(874)|
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
历史上的今天
在LOFTER的更多文章
loftPermalink:'',
id:'fks_',
blogTitle:'Java深入 - Java 内存分配和回收机制',
blogAbstract:'Java的GC机制是自动进行的,和c语言有些区别需要程序员自己保证内存的使用和回收。Java的内存分配和回收也主要在Java的堆上进行的,Java的堆中存储了大量的对象实例,所以Java的堆也叫GC堆。Java在垃圾收集的过程中,主要用到了分代收集算法,我会先讲一下常用垃圾收集算法。',
blogTag:'',
blogUrl:'blog/static/',
isPublished:1,
istop:false,
modifyTime:0,
publishTime:7,
permalink:'blog/static/',
commentCount:0,
mainCommentCount:0,
recommendCount:0,
bsrk:-100,
publisherId:0,
recomBlogHome:false,
currentRecomBlog:false,
attachmentsFileIds:[],
groupInfo:{},
friendstatus:'none',
followstatus:'unFollow',
pubSucc:'',
visitorProvince:'',
visitorCity:'',
visitorNewUser:false,
postAddInfo:{},
mset:'000',
remindgoodnightblog:false,
isBlackVisitor:false,
isShowYodaoAd:false,
hostIntro:'',
hmcon:'1',
selfRecomBlogCount:'0',
lofter_single:''
{list a as x}
{if x.moveFrom=='wap'}
{elseif x.moveFrom=='iphone'}
{elseif x.moveFrom=='android'}
{elseif x.moveFrom=='mobile'}
${a.selfIntro|escape}{if great260}${suplement}{/if}
{list a as x}
推荐过这篇日志的人:
{list a as x}
{if !!b&&b.length>0}
他们还推荐了:
{list b as y}
转载记录:
{list d as x}
{list a as x}
{list a as x}
{list a as x}
{list a as x}
{if x_index>4}{break}{/if}
${fn2(x.publishTime,'yyyy-MM-dd HH:mm:ss')}
{list a as x}
{if !!(blogDetail.preBlogPermalink)}
{if !!(blogDetail.nextBlogPermalink)}
{list a as x}
{if defined('newslist')&&newslist.length>0}
{list newslist as x}
{if x_index>7}{break}{/if}
{list a as x}
{var first_option =}
{list x.voteDetailList as voteToOption}
{if voteToOption==1}
{if first_option==false},{/if}&&“${b[voteToOption_index]}”&&
{if (x.role!="-1") },“我是${c[x.role]}”&&{/if}
&&&&&&&&${fn1(x.voteTime)}
{if x.userName==''}{/if}
网易公司版权所有&&
{list x.l as y}
{if defined('wl')}
{list wl as x}{/list}1.什么叫内存泄漏?简单来说就是一个东西放在内存里的时间太长了,当你的程序都跑完了,它还存在那里。这时它是白白的占用了你的内存,累积起来占用的内存越来越多……最后就会导致JVM报错:out of memory。他占用的是我们的物理内存。2.java内存泄漏的根本原因是?内存对象明明已经不需要的时候,还仍然保留着这块内存和它的访问方式(引用)。3.java既然存在gc线程,为什么还存在内存泄漏?这个问题,我们需要知道 GC 在什么时候回收内存对象,什么样的内存对象会被 GC 认为是“不再使用”的。Java中对内存对象的访问,使用的是引用的方式。在 Java 代码中我们维护一个内存对象的引用变量,通过这个引用变量的值,我们可以访问到对应的内存地址中的内存对象空间。在 Java 程序中,这个引用变量本身既可以存放堆内存中,又可以放在代码栈的内存中(与基本数据类型相同)。 GC 线程会从代码栈中的引用变量开始跟踪,从而判定哪些内存是正在使用的。如果 GC 线程通过这种方式,无法跟踪到某一块堆内存,那么 GC 就认为这块内存将不再使用了(因为代码中已经无法访问这块内存了)。通过这种有向图的内存管理方式,当一个内存对象失去了所有的引用之后,GC 就可以将其回收。反过来说,如果这个对象还存在引用,那么它将不会被 GC 回收,哪怕是 Java 虚拟机抛出 OutOfMemoryError 。例子1:Vector v = new
Vector( 10 );
i = 1 ;i & 100 ; i ++ ){
Object o = new
}在这个例子中,代码栈中存在Vector 对象的引用 v 和 Object 对象的引用 o 。
在 For 循环中,我们不断的生成新的对象,然后将其添加到 Vector 对象中,之后将 o 引用置空。问题是当 o 引用被置空后,
如果发生 GC ,
我们创建的 Object 对象是否能够被 GC 回收呢?
答案是否定的。
因为, GC 在跟踪代码栈中的引用时,
会发现 v 引用,而继续往下跟踪,就会发现 v 引用指向的内存空间中又存在指向 Object 对象的引用。也就是说尽管 o 引用已经被置空,
但是 Object 对象仍然存在其他的引用,是可以被访问到的,所以 GC 无法将其释放掉。
如果在此循环之后, Object 对象对程序已经没有任何作用,
那么我们就认为此 Java 程序发生了内存泄漏。例子2:如果想要看到内存溢出,可以按这样的思路去尝试一下:定义一个静态的(list或其它集合),然后在一个方法里循环往这个静态变量塞东西,直到这个实例变量撑爆你的jvm内存。很快你就能看到out of memory……import java.util.ArrayLimport java.util.L public class MemoryTest {
private static List list = new ArrayList();
private static int count = 0;
public static void main(String[] args) throws InterruptedException {
System.out.println("申请前的可用内存 = "+getFreeMemory());
while(true){
list.add(new byte[1024*1024]);
if (count % 100 == 0) {
System.out.println("当前list.size()="+list.size()+",可用内存 = "+getFreeMemory());
Thread.sleep(500);
public static long getFreeMemory() {
return Runtime.getRuntime().freeMemory() / (1024 * 1024);
} }所以我们要慎用类变量。
Java有自己的内存回收机制,但为什么还存在内存泄露的问题呢?
原文地址:https://www.cnblogs.com/panxuejun/p/5888817.html
1.既然 Java 的垃圾回收机制能够自动的回收内存,怎么还会出现内存泄漏的情况呢?这...
java中的垃圾回收机制及内存泄漏的现象
一、java中的垃圾回收机制
在传统语言C/C++中,程序员要手动回收过期的内存,而java在这方面便有属于自己自动回收过期内存的机制。
在JVM虚拟机提供了一个系统级的java垃圾回收线程GC(Ca...
java对于垃圾回收机制[GC垃圾回收机制]
为什么有GC还会有内存溢出呢?
java垃圾回收机制
来源于书本和工作中的总结。
如果分配出去的内存得不到释放,及时回收,就会引起系统运行速度下降,甚至导致程序瘫痪,这就是内存泄露
java内存分配和...
java虽然有垃圾回收机制,还是有内存泄漏现象的
其实java有内存泄漏现象垃圾回收机制只能回收没有引用的对象,也就是说只能回收没有“指针”的对象,对于非引用类对象,垃圾回收机制就不能起作用比如说,如果打开过多的数据库连接,那么这些不能被垃圾回收机...
JS的垃圾回收机制了解吗?
Js具有自动垃圾回收机制。垃圾收集器会按照固定的时间间隔周期性的执行。
JS中最常见的垃圾回收方式是标记清除。
工作原理:是当变量进入环境时,将这个变量标记为...
在segmentfault上看到一个问题:java有完善的GC机制,那么在java中是否会出现内存泄漏的问题,以及能否给出一个内存泄漏的案例。本问题视图给出此问题的完整答案。
程序运行的时候需要内存,只要程序提出要求,操作系统就要给它分配内存,而随着持续的运行这些进程,必须及时释放不再用到的内存,否则轻则影响系统性能,重则导致进程崩溃。
不再用到的内存...
其实java有内存泄漏现象垃圾回收机制只能回收没有引用的对象,也就是说只能回收没有“指针”的对象,对于非引用类对象,垃圾回收机制就不能起作用比如说,如果打开过多的数据库连接,那么这些不能被垃圾回收机制...
http://www.2cto.com/kf/419.htmlhttp://www.cnblogs.com/nele/p/5673215.html1.引用计数算法引用计数(...
1.既然 Java 的垃圾回收机制能够自动的回收内存,怎么还会出现内存泄漏的情况呢?这个问题,我们需要知道 GC 在什么时候回收内存对象,什么样的内存对象会被 GC 认为是“不再使用”的。Java中对...
没有更多推荐了,Java程序要求用户必须手工创建一个线程来释放内存
Java程序允许用户使用指针来释放内存
内存回收线程负责释放无用内存
内存回收线程不能释放内存对象
java虚拟机中的垃圾回收机制是一个类,当该对象没有更多的应用指向它时,就会被垃圾回收器给回收,从而释放资源。该机制不可以程序员手动调用去回收某个对象,系统自动回去调用,当然程序员可以建议垃圾回收器回收某个对象。所以java中无需程序员手动释放内存,系统自动释放无用内存。
Java中GC机制,开发人员不能人工参与,虽然可以调用System.gc(),但是这个方法只是一个提醒,具体什么时候GC,还是不知道。
多说一句,System.gc()这个东西提醒的是Full GC,不是Minor GC。
内存回收线程可以释放无用的对象内存
正确答案:C
这道题你会答吗?花几分钟告诉大家答案吧!
扫描二维码,关注牛客网
下载牛客APP,随时随地刷题
京ICP备号-4
扫一扫,把题目装进口袋在 SegmentFault,学习技能、解决问题
每个月,我们帮助 1000 万的开发者解决各种各样的技术问题。并助力他们在技术能力、职业生涯、影响力上获得提升。
问题对人有帮助,内容完整,我也想知道答案
问题没有实际价值,缺少关键内容,没有改进余地
既然 Java 的垃圾回收机制能够自动的回收内存,怎么还会出现内存泄漏的情况呢
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
内存资源是有限的,垃圾回收只回收“垃圾”,对于你的程序运行有用的对象不会被回收。
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
内存溢出分两种情况:一种是栈溢出,比如调用了一个无限递归。还有一种是堆溢出,即new 出来的对象没有即使销毁,比如一直new。
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
因为有些写的很蠢的程序会在GC机制生效之前无限地创建对象。
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
一般来说,Java中的内存泄漏指的是已经不再被程序需要的已分配内存无法被回收。垃圾回收机制通过对象与Root对象的可达性判断内存是否可以被回收,但由于编程错误或其他原因,导致过期的对象引用仍然被持有,垃圾回收器无法回收相关空间。
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
占着茅坑不拉屎,他也没办法.推荐看下我同事写的博客:
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
一些对象其实不需要了但却一直被引用,没办法回收
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
就目前来说,人做的东西还不能超越人本身,java的GC算法是人写出来的,奈何就有人会作死写出让GC无法回收的代码来
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
这就如同中国那么大,为什么还有人在朝阳区懵逼一样。
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
我自己的理解,说的不对的地方欢迎指正。JDK6中,String的一个方法叫subString,这个是用来生成一个子字符串的。为了更加快速的生成,String有一个构造函数,String(int offset, int count, char value[]) {
this.value =
this.offset =
this.count =
}直接指向了原来String的数组。我们都知道,每次都会生成一个新的常量池中的String字符串。然而这个引用就导致了原来的String无法被回收。因为subString的value会指向他。这里就会导致内存泄露。
JVM的确是自己进行GC的,不用程序员过多干涉,但是由于一些错误操作,导致一些本来不在需要使用的对象仍然有引用,才会导致内存泄露的。
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
JVM:程序员抓着垃圾不放,我也很为难啊。
同步到新浪微博
分享到微博?
关闭理由:
删除理由:
忽略理由:
推广(招聘、广告、SEO 等)方面的内容
与已有问题重复(请编辑该提问指向已有相同问题)
答非所问,不符合答题要求
宜作评论而非答案
带有人身攻击、辱骂、仇恨等违反条款的内容
无法获得确切结果的问题
非开发直接相关的问题
非技术提问的讨论型问题
其他原因(请补充说明)
我要该,理由是:
在 SegmentFault,学习技能、解决问题
每个月,我们帮助 1000 万的开发者解决各种各样的技术问题。并助力他们在技术能力、职业生涯、影响力上获得提升。java有垃圾回收机制,为什么还会出现内存溢出_百度知道
java有垃圾回收机制,为什么还会出现内存溢出
答题抽奖
首次认真答题后
即可获得3次抽奖机会,100%中奖。
<span class="wgt-replyer-all-uname
" data-href="https://zhidao.baidu.com/usercenter?uid=1cdf05e57lihao
<span class="wgt-replyer-all-card-name3 wgt-replyer-all-card-names" data-href="https://zhidao.baidu.com/usercenter?uid=1cdf05e57lihao
采纳数:27
获赞数:90
擅长:暂未定制
class&Main{&&&&private&List&Object&&list&=&new&ArrayList&Object&();&&&&&public&static&void&main(String[]&args){&&&&&&&&Main&main&=&new&Main();&&&&&&&&while(true){&&&&&&&&&&&&Object&obj&=&new&Object();&&&&&&&&&&&&main.list.add(obj);&&&&&&&&}&&&&}}你觉得会溢出嘛。
为你推荐:
其他类似问题
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。}

我要回帖

更多关于 请简述Java的内存回收机制 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信