JVM内存结构、垃圾回收那点事(转)
翻看电脑的文件夹,无意看到了9月份在公司做的一次分享,浏览了一下"婆婆特",发现自己在ppt上的写的引导性问题自己也不能确切的回答出来,哎,知识这东西,平时不常用的没些日子就生疏了。于是,本小白决定把他整理下来,不敢班门弄斧,对于入门的同学可以快速了解虚拟机的大概,有错误的地方请批评指正。
一、java虚拟机的内存结构

方法区:线程共享,存放已被虚拟机加载的常量,静态变量,类信息,即时编译后的代码等数据。

public class ReferenceCountGc {
public Object field = null;
public static void main(String[] args) {
ReferenceCountGc objA = new ReferenceCountGc();
ReferenceCountGc objB = new ReferenceCountGc();
objA.field = objB;
objB.field = objA;
objA = null;
objB = null;
System.gc();
}
}
当程序执行到System.gc()时,是否会回收对象objA和objB?
引用计数方法:给对象一个计数器,当对象被引用时就+1,释放掉引用-1,当为0时及不会再被引用。但引用计数方法的Bug是无法解决对象循环引用的问题,但并不是此算法没有用武之地,在很多场景下会使用到这个算法。但java的垃圾回收并没有使用。上面的程序如果使用的是引用计数算法则不会被回收,但虚拟机却使用根搜索算法。
根搜索算法即设定一个对象称为GC root ,从这个节点向下进行搜索,搜索所走过的路径称为引用链,当GC root没有任何引用链相连即在图论中不可到达,则证明此对象不可用
由此来看看,对象死后,垃圾回收算法;
标记-清除算法 复制算法

灰色矩形框为可回收对象,标记-清除算法就是把可回收的对象进行标记,标记到一定次数则清除掉。从图中可以明显看出,该算法的弊端是会产生大量的磁盘碎片,没有一整片连续的空间,当遇到占用连续的内存空间较多的对象时,由于内存放不下该对象,会提前进行垃圾回收,致使虚拟机垃圾回收频繁,影响性能
为了规避标记清除算法的弊端,出现了复制算法,复制算法将内存一份为二,垃圾回收时将使用的内存中的存活对象,拷贝到另一半内存中,然后把左侧内存区域完全清除掉,上图只是演示了复制算法,但并非一分为二,使用和保留的空间是1:1,可以根据实际情况对虚拟机参数进行调整。此算法的弊端是要保留内存空间,会将可用内存变少。
标记整理算法: 分代收集算法:

标记整理算法:绿色和蓝色区域都代表存活对象,当进行垃圾回收时把存活对象依次移到最左边,移动后将其余内存空间清空。
分代收集算法:如图,其实就是没有算法。。。把以上3种算法进行综合运用,前面说过堆是有划分的,简单分为新生代和老年代,分代收集就是根据不同代的特点应用不同的垃圾回收算法。
三、java内存分配
java的自动内存管理解决了两个问题,一是给对象分配内存,二是回收分配给对象的内存,前面我们讲了回收分配给对象的内存,下面我们来看看给对象分配内存

java堆分为新生代,老年代(终身代)和永久代。
新生代和老年代的默认比值为1:2即新生代占堆总内存的1/3,可以通过 –Xms(初始堆大小)、-Xmx (最大堆大小)来改变。
新生代又分为Eden区、From survivor区、To survivor区,Eden:From:To 为 8:1:1,可以通过–XX:SurvivorRatio 参数设定。
JVM每次只会使用From区和survivor区中的一块(Form survivor或To survivor),很明显是为了在垃圾回收的时候将存活对象移到另外一个空闲的survivor区(如果空间足够,否则直接进入老年代),因此垃圾回收所使用的算法是复制算法。
新生的对象会被分配到新生代,新生代的特点是朝生夕死,对象存活的时间短,迭代快。发生在新生代的垃圾回收叫minor GC,minor Gc进行的相对频繁,消耗较full GC少,而Full GC是发生在老年代的垃圾回收,采用的是标记-清除算法。老年代进行一次垃圾回收比新生代话费时间长,进行的也没有老年代频繁,同时要尽量减少老年代的垃圾回收,因为回收速度慢且在进行时影响虚拟机性能,使虚拟机响应变慢,最直接的感觉是应用程序的响应速度变慢。
什么情况下,对象会被分配到老年代?

从上图中明显可以到3点:
大对象:什么是大对象,大对象就是需要连续占用很多内存空间的对象比如很长的字符串和数组。虚拟机通过-XX:PretrnureSizeThreshold设计大过指定大小的对象之间进入老年代,即时没有超过指定大小,在进行minor GC时通常也会因为survivor区不够用而被转移到老年代。
通过设置MaxTenuringThreshold参数: 这个参数是进行年龄设置的,超过这个年龄的会进入老年代。什么是年龄?在新生代进行minor GC的时候,每进行一次,存活下来的对象年龄+1,默认年龄超过15的会进入老年代。15这个数值也可以通过MaxTenuringThreshold参数改变。
Survivor空间中相同年龄所有对象大小的总和大于survivor空间的一半,所有大于或者等于该年龄的对象直接进入老年代,这句话比较拗口,但就是这个意思,看不懂的多看几遍就好了。。。
前面讲了这么多参数,如何设置虚拟机参数?可以通过IDE进行设置,不论是调整空间大小,还是设置对象的年龄进入老年代,如下图

三、我们开发中应注意的问题
从虚拟机上可以看出,主要是避免full GC的次数,减少朝生夕死的大对象,对虚拟机内存进行优化,在日常开发中写程序的主要注意的是
不要使用长字符串 如:String x = new String(“XXXXXXXXXXXX”) StringBuffer stringBuffer = new StringBuffer()StringBuffer对象的append()方法。当然,考虑到线程安全问题,使用StringBuilder.
JVM内存结构、垃圾回收那点事(转)的更多相关文章
- Java进阶 JVM 内存与垃圾回收篇(一)
JVM 1. 引言 1.1 什么是JVM? 定义 Java Vritual Machine - java 程序的运行环境(Java二进制字节码的运行环境) 好处 一次编译 ,到处运行 自动内存管理,垃 ...
- Java内存与垃圾回收调优
Java(JVM)内存模型 正如你从上面的图片看到的,JVM内存被分成多个独立的部分.广泛地说,JVM堆内存被分为两部分——年轻代(Young Generation)和老年代(Old Generat ...
- 【转】Java内存与垃圾回收调优
要了解Java垃圾收集机制,先理解JVM内存模式是非常重要的.今天我们将会了解JVM内存的各个部分.如何监控以及垃圾收集调优. Java(JVM)内存模型 正如你从上面的图片看到的,JVM内存被分成多 ...
- 面试~jvm(JVM内存结构、类加载、双亲委派机制、对象分配,了解垃圾回收)
一.JVM内存结构 ▷ 谈及内存结构各个部分的数据交互过程:还可以再谈及生命周期.数据共享:是否GC.是否OOM 答:jvm 内存结构包括程序计数器.虚拟机栈.本地方法栈.堆.方法区:它是字节码运行时 ...
- 推荐收藏系列:一文理解JVM虚拟机(内存、垃圾回收、性能优化)解决面试中遇到问题(图解版)
欢迎一起学习 <提升能力,涨薪可待篇> <面试知识,工作可待篇 > <实战演练,拒绝996篇 > 欢迎关注我博客 也欢迎关注公 众 号[Ccww笔记],原创技术文章 ...
- 【转】jvm内存结构
JVM的基本结构 包括四部分:类加载器.执行引擎.内存区(运行时数据区).本地方法接口 类加载器:jvm启动时或类运行时将需要的class文件加载到JVM中. JVM内存申请过程如下: JVM 会试图 ...
- 【JVM】JVM系列之垃圾回收(二)
一.为什么需要垃圾回收 如果不进行垃圾回收,内存迟早都会被消耗空,因为我们在不断的分配内存空间而不进行回收.除非内存无限大,我们可以任性的分配而不回收,但是事实并非如此.所以,垃圾回收是必须的. 二. ...
- JVM内存结构之三--持久代
本文会介绍一些JVM内存结构的基本概念,然后很快会讲到持久代,来看下Java SE 8发布后它究竟到哪去了. 基础知识 JVM只不过是运行在你系统上的另一个进程而已,这一切的魔法始于一个java命令. ...
- 最简单例子图解JVM内存分配和回收
一.简介 JVM采用分代垃圾回收.在JVM的内存空间中把堆空间分为年老代和年轻代.将大量(据说是90%以上)创建了没多久就会消亡的对象存储在年轻代,而年老代中存放生命周期长久的实例对象.年轻代中又被分 ...
- JVM内存结构
前言 在Java语言开发过程中,out of memory错误是很常见的一种错误.对于JVM的内存结构有更深入的了解,更更好的帮我们排查此类问题,有效的避免此类问题发生.在JAVA 8中内存结构有进行 ...
随机推荐
- 使用Google Roads API抓取道路信息(java实现)
Google Roads API提供了强大的道路获取接口,用户仅仅需调用对应的API就能够获取对应区域的道路坐标以及道路的限速信息. 详细的调用方法例如以下: https://roads.google ...
- Gnu Linux--Ubuntu系统清理项整理
/********************************************************************* * Author : Samson * Date ...
- Netbeans源代码编辑技巧——使用代码补全和代码生成
原文 Netbeans源代码编辑技巧——使用代码补全和代码生成 使用代码补全生成代码 一般来说,代码补全对于自动填充缺失的代码是有帮助的,例如标识符和关键字.截至 NetBeans IDE 6.0,您 ...
- Spring Data Redis—Pub/Sub(附Web项目源码) (转)
一.发布和订阅机制 当一个客户端通过 PUBLISH 命令向订阅者发送信息的时候,我们称这个客户端为发布者(publisher). 而当一个客户端使用 SUBSCRIBE 或者 PSUBSCRIBE ...
- 在android创建bitmap避免低记忆法
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="ht ...
- freemarker导出word带图片
导出word带图片 如果你需要在word中添加图片,那你就在第一步制作模板时,加入一张图片占位,然后打开xml文档,可以看到如下的一片base64编码后的代码: <w:binData w:nam ...
- java 通过sftp服务器上传下载删除文件
最近做了一个sftp服务器文件下载的功能,mark一下: 首先是一个SftpClientUtil 类,封装了对sftp服务器文件上传.下载.删除的方法 import java.io.File; imp ...
- Apache James使用的方法及相关心得(转)
经过一番的辛苦努力,终于把James 配置搞定啦,好记性不如烂笔头啊,赶紧记下我的成功经过,以备以后查阅! 首先要做的就是配置域名的MX 记录啦: 先添加一条A记录: mail.abc.com 指向 ...
- Android该HTTP下载
今天学习了Android开发中比較难的一个环节,就是断点续传下载,非常多人看到这个标题就感觉头大.的确,假设没有良好的逻辑思维,这块的确非常难搞明确.以下我就将自己学到的知识和一些见解写下供那些在这个 ...
- 矩阵快速幂---BestCoder Round#8 1002
当要求递推数列的第n项且n很大时,怎么快速求得第n项呢?可以用矩阵快速幂来加速计算.我们可以用矩阵来表示数列递推公式比如fibonacci数列 可以表示为 [f(n) f(n-1)] = [f(n ...