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 程序计数器 程序计数器( ...
随机推荐
- 使用bison和yacc制作脚本语言(4)
我们现在开始设计数据结构: interpreter.h #ifndef INTERPRETER #define INTERPRETER #include "../include/eval.h ...
- Making AJAX Applications Crawlable
https://developers.google.com/webmasters/ajax-crawling/
- C#实现窗口最小化到系统托盘
先添加notifyicon控件notifyIcon1 using System; using System.Collections.Generic; using System.ComponentMod ...
- Centos 7 快速安装 Docker
摘要: 安装 Docker [root@localhost~]# yum install docker 启动 docker 服务 [root@localhost~]# systemctl start ...
- python爬取视频网站m3u8视频,下载.ts后缀文件,合并成整视频
最近发现一些网站,可以解析各大视频网站的vip.仔细想了想,这也算是爬虫呀,爬的是视频数据. 首先选取一个视频网站,我选的是 影视大全 ,然后选择上映不久的电影 “一出好戏” . 分析页面 我用的是c ...
- 网站端测试常见BUG
1.翻页 翻页时,没有加载数据为空,第二页数据没有请求 翻页时,重复请求第一页的数据 翻页时,没有图片的内容有时候会引用有图片的内容 2.图片数据为空 图片数据为空时,会保留为空的图片数据位置 3.链 ...
- MySQL☞having子句
having子句:是跟group by结合使用,对分组以后的数据再次进行过滤,经常跟聚合函数结合使用 格式: select 列名/聚合函数 from 表名 where 条件 group by ...
- Linux命令应用大词典-第31章 设备管理
31.1 udevadm info:查询udev数据库中的设备信息 31.2 mkdnod:创建块设备和字符设备文件 31.3 MAKEDEV:创建/dev中的设备 31.4 lsblk:列出块设备信 ...
- 下落的树叶 (The Falling Leaves UVA - 699)
题目描述: 原题:https://vjudge.net/problem/UVA-699 题目思路: 1.依旧二叉树的DFS 2.建树过程中开个数组统计 //紫书源代码WA AC代码: #include ...
- 悲剧文本(Broken Keyboard (a.k.a. Beiju Text),UVA 11988)
题目描述: 题目思路: 1.使用链表来重新定位各个字符 2.用数组实现链表 3.开一个数组list[i]来存储字符数组下一个字符的位置 #include <iostream> #inclu ...

