Java内存分配及垃圾回收机制
Java内存区域
1、内存区域
jvm运行时数据区域
- 程序计数器
- Java虚拟机栈
- 本地方法栈
- 方法区
- Java堆
大图

2、概念解释
程序计数器
线程私有的一块很小的内存空间,它是当前线程所执行的字节码的行号指示器。字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成。每个线程都对应一个独立的程序计数器, 记录着线程执行指令,保障了线程间的切换后能恢复到正确的执行位置,从而保障了Java虚拟机多线程能有条不紊地轮流切换执行。Java虚拟机栈
线程私有, 它的生命周期与线程相同。虚拟机栈描述的是Java方法执行的内存模型:每个方法被执行的时候都会同时创建一个栈帧用于存储局部变量表、操作栈、动态链接、方法出口等信息。每一个方法被调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。本地方法栈
为虚拟机使用到的native方法服务, 其作用类似于Java虚拟机栈, 只不过虚拟机栈为虚拟机执行Java方法(也就是字节码)服务。方法区
各个线程共享的内存区域, 用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。方法区也是我们通常所说的永久区,它的大小可通过参数-XX:PermSize、-XX:MaxPermSize进行设置Java堆
Java堆是Java虚拟机所管理的内存中最大的一块, 被所有线程共享的一块内存区域, 在虚拟机启动时创建,是存储Java对象实例的地方。Java堆细分为:新生代和老年代,而新生代又可细分为Eden空间、from survivor空间、to survivor空间等。
根据JVM规范,Java堆可以处于物理上不连续的内存空间中。只要逻辑上是连续的即可。可通过-Xmx设置最大Java堆的大小,-Xms设置初始化时Java堆大小。
3、为了更好理解堆、栈、方法区, 以下举个栗子
来,先看下一段代码
import java.text.SimpleDateFormat;
import java.util.Date;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* mvp
* @author yuanmeng
* @create 2017-06-18 下午8:44
**/
public class MVP {
private static Logger LOG = LoggerFactory.getLogger(MVP.class);
public void winMVP(String name) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
String today = sdf.format(new Date());
LOG.info("威少 mvp");
}
}
这段程序的数据信息在内存中存放如下图所示:

垃圾收集器
**1)检测垃圾机制 **
Java运行时所加载的数据, 如类信息、实例对象信息等会占用系统内存, 所幸的是Java有个强大的垃圾收集器, 在内存不够分配对象的时候会触发GC。
检测垃圾的方法常见的有两种:1. 引用计数法;2. 可达性分析算法。
引用计数法
给对象附加一个引用计数器,只要有一个地方引用它,计数器值加1。当引用失效时就减1。任何时刻计数器都为0的对象就是不可能再被使用的,将其判定为可回收的对象。这种检测机制的优点是很简单, 但它有个很致命的缺点,它无法解决对象间循环引用问题。如hashMap在高并发的时候会出现循环链表问题。可达性分析算法
主流的JVM基本都使用可达性分析算法来判断对象是否存活,通过一系列“GC Roots”的对象作为起始点向下搜索,搜索所走过的路径为引用链,当一个对象没有任何引用链与GC Roots相连,代表该对象不再被使用,将其判定为可回收的对象。
看下图,Object5 、Object6、Object7是从跟节点出发无法可达到的对象, 可判定为回收对象。

2)回收垃圾机制
标记-清除算法
先标记待回收的对象,然后再对标记的对象进行清除。图解

这种算法缺点 :- 标记和清除两个过程, 效率不高
- 标记清除后会产生大量不连续内存碎片, 多次进行标记和清除回收后可能会导致以后程序在运行过程中需要分配大对象时,无法找到足够的连续内存而不得不提前出发GC,而GC需要耗时间。
复制算法
复制算法是将内存分成两块,一块存储程序运行分配的对象,一块是空闲区域。当存储对象的内存区域用完了,会将此区域存活的对象复制到另一块空闲区域,然后再把已使用的内存空间一次清理掉。

复制算法实现简单、高效。但代价有点大了,可用内存缩小为原来的一半,以“空间换取时间”。
- 标记-整理算法
标记-整理算法是对原有标记-清除算法进行的改造,不是直接对可回收对象进行清理,而是让所有存活对象都向另一端移动,然后直接清理掉端边界以外的内存。

- 分生代算法
前面也介绍过了,Java堆内存可以细分为新生代、老年代。新生代生存的生命周期比较短,每次经过GC后仍存活的对象年龄会加1, 多次GC后仍存活的对象会直接晋升为老年代。而老年代的生命周期比较长。换句话说,每次GC后新生代生存下来的对象很少,老年代存活对象多。前面分析过,生存对象少的新生代更适合用复制算法,生存对象多的老年代适合用标记-清除或者标记-整理算法
参考文献
《深入理解Java虚拟机》
写在最后
Java内存分配及垃圾回收机制的更多相关文章
- Java内存分配及垃圾回收机制(未完待待续)
Java内存区域 1.内存区域 jvm运行时数据区域 程序计数器 Java虚拟机栈 本地方法栈 方法区 Java堆 大图 2.概念解释 程序计数器 线程私有的一块很小的内存空间,它是当前线程所执行 ...
- Java 内存分配及垃圾回收机制初探
一.运行时内存分配 Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域. 这些区域都有各自的用途,以及创建和销毁的时间,有的区域随着虚拟机进程的启动而存在,有些区域则 ...
- JVM内存分配与垃圾回收机制管理
项目上线,性能优化有个重要组成就是jvm内存分配和垃圾回收机制的管理配置. 网上随便能搜到相关的具体步骤,以及内存中各种参数对应的意义,不再赘述. 干货就是直接抛出遇到的问题,以及如何解决的,再说说待 ...
- java基础(一):谈谈java内存管理与垃圾回收机制
看了很多java内存管理的文章或者博客,写的要么笼统,要么划分的不正确,且很多文章都千篇一律.例如部分地方将jvm笼统的分为堆.栈.程序计数器,这么分太过于笼统,无法清晰的阐述java的内存管理模型: ...
- java内存分配与垃圾回收
JVM的内存分配主要基于两种,堆和栈. 我们来看一下java程序运行时候的内存分配策略: 1):静态存储区(方法区): 2):栈区: 3):堆区: 1):主要存放静态数据,全局static数据和常量. ...
- 巩固java(二)----JVM堆内存结构及垃圾回收机制
前言: 我们在运行程序时,有时会碰到内存溢出(OutOfMemoryError)的问题,为了解决这种问题,我们有必要了解JVM的内存结构和垃圾回收机制. 正文: 1.JVM堆内存结构 ...
- Java中内存泄露及垃圾回收机制
转自:http://blog.sina.com.cn/s/blog_538b279a0100098d.html 写的相当不错滴...................... 摘 要 Java语言中,内 ...
- JVM原理(Java代码编译和执行的整个过程+JVM内存管理及垃圾回收机制)
转载注明出处: http://blog.csdn.net/cutesource/article/details/5904501 JVM工作原理和特点主要是指操作系统装入JVM是通过jdk中Java.e ...
- 【Java_基础】JVM内存模型与垃圾回收机制
1. JVM内存模型 Java虚拟机在程序执行过程会把jvm的内存分为若干个不同的数据区域来管理,这些区域有自己的用途,以及创建和销毁时间. JVM内存模型如下图所示 1.1 程序计数器 程序计数器( ...
随机推荐
- Java多线程一些基础知识
最近复习了一些多线程方面的基础知识,做一下总结,多以自己的理解来文字叙述,如果有漏点或者理解错的地方,欢迎各位大佬多多指出: ps:线程分为用户线程和守护线程,当程序中的所有的用户线程都执行完了之后, ...
- MySQL入门第三天(下)——存储过程与存储引擎
一.存储过程 1.简介 原始的SQL执行的流程: 通过存储过程,便可以简化以上流程,那么存储过程是什么,如何进行性能提高呢? 是什么? 存储过程是可编程的函数,在数据库中创建并保存,可以由SQL语句和 ...
- 网络流Edmonds-Karp算法入门
今天自习课没事干,看书自学了一下网络流中的EK算法.(求最大流) 设s为源点,t为汇点,C为容量矩阵,F为流量矩阵,f为最大流量. 1.初始化F,f 2.用BFS在残量网络中找到一条从s到t的最短增广 ...
- 深圳Uber优步司机奖励政策(12月28日到1月3日)
滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...
- treetable--.net webform中树形table表管理的应用
好记性不如烂笔头. treetable 官网:http://ludo.cubicphuse.nl/jquery-treetable/#api 今天要做一个关于table的树节点展示,还有编辑,删除功能 ...
- springboot整合kafka应用
1.kafka在消息传递的使用非常普遍,相对于activemq来说kafka的分布式管理和使用更加灵活. 2.activemq的搭建和使用可以参考: activemq搭建和springmvc的整合:h ...
- FreeRTOS信号量的封装函数参数是二级指针
1. 先看正确的封装方式,问题所在,为什么要用2级指针 void cissys_lockcreate(void** mutex) { //创建信号量,应该是互斥锁 *mutex = ((Semapho ...
- MySQL 取得字段子串修改
MySQL 中, GeneID 为 GRMZM2G549533_P01,1123,45 , 需要修改为 GRMZM2G549533_P01 update test set GeneID=SUBSTRI ...
- keepalived+nginx实现高可用+tomcat
1.keepalived的yum安装 安装依赖包[root@localhost ~]# yum install -y curl gcc openssl-devel libnl3-devel net-s ...
- lintcode: Missing String
Missing String 描述: Given two strings, you have to find the missing string. Have you met this questi ...

