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内存分配及垃圾回收机制的更多相关文章

  1. Java内存分配及垃圾回收机制(未完待待续)

    Java内存区域 1.内存区域 jvm运行时数据区域 程序计数器 Java虚拟机栈 本地方法栈 方法区 Java堆 大图 2.概念解释 程序计数器   线程私有的一块很小的内存空间,它是当前线程所执行 ...

  2. Java 内存分配及垃圾回收机制初探

    一.运行时内存分配 Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域. 这些区域都有各自的用途,以及创建和销毁的时间,有的区域随着虚拟机进程的启动而存在,有些区域则 ...

  3. JVM内存分配与垃圾回收机制管理

    项目上线,性能优化有个重要组成就是jvm内存分配和垃圾回收机制的管理配置. 网上随便能搜到相关的具体步骤,以及内存中各种参数对应的意义,不再赘述. 干货就是直接抛出遇到的问题,以及如何解决的,再说说待 ...

  4. java基础(一):谈谈java内存管理与垃圾回收机制

    看了很多java内存管理的文章或者博客,写的要么笼统,要么划分的不正确,且很多文章都千篇一律.例如部分地方将jvm笼统的分为堆.栈.程序计数器,这么分太过于笼统,无法清晰的阐述java的内存管理模型: ...

  5. java内存分配与垃圾回收

    JVM的内存分配主要基于两种,堆和栈. 我们来看一下java程序运行时候的内存分配策略: 1):静态存储区(方法区): 2):栈区: 3):堆区: 1):主要存放静态数据,全局static数据和常量. ...

  6. 巩固java(二)----JVM堆内存结构及垃圾回收机制

    前言:        我们在运行程序时,有时会碰到内存溢出(OutOfMemoryError)的问题,为了解决这种问题,我们有必要了解JVM的内存结构和垃圾回收机制. 正文: 1.JVM堆内存结构   ...

  7. Java中内存泄露及垃圾回收机制

    转自:http://blog.sina.com.cn/s/blog_538b279a0100098d.html 写的相当不错滴...................... 摘  要 Java语言中,内 ...

  8. JVM原理(Java代码编译和执行的整个过程+JVM内存管理及垃圾回收机制)

    转载注明出处: http://blog.csdn.net/cutesource/article/details/5904501 JVM工作原理和特点主要是指操作系统装入JVM是通过jdk中Java.e ...

  9. 【Java_基础】JVM内存模型与垃圾回收机制

    1. JVM内存模型 Java虚拟机在程序执行过程会把jvm的内存分为若干个不同的数据区域来管理,这些区域有自己的用途,以及创建和销毁时间. JVM内存模型如下图所示 1.1 程序计数器 程序计数器( ...

随机推荐

  1. go学习笔记-标准库

    标准库 名称 摘要 archive tar tar包实现了tar格式压缩文件的存取. zip zip包提供了zip档案文件的读写服务. bufio bufio 包实现了带缓存的I/O操作. built ...

  2. Java基础之static关键字的用法

    Java中的static关键字主要用于内存管理.我们可以应用static关键字在变量.方法.块和嵌套类中. static关键字属于类,而不是类的实例.        静态(static)可以是: 变量 ...

  3. DE4加DVI子板实现静态图片显示

    20170906录一下 内容后续补充

  4. Windows下的SysWow64和System32

    64位的Windows并不是简单地把所有东西都编译成64位就万事大吉的.关于64位的CPU应该做成什么样子,Intel和AMD曾有各自的打算.AMD的回答直接了当:新的64位处理器,应该能在提高更高处 ...

  5. 全新Ubuntu-13.04安装配置redmine

    1. apt-get install  vim  apache2 libapache2-mod-passenger ruby rubygems libruby ruby-dev  libmagickc ...

  6. 一 Hive安装及初体验

    一 .Hive安装及初体验 1 .hive简介 Hive是基于Hadoop的一个数据仓库工具,可以将结构化的数据文件映射为一张数据库表,并提供类SQL查询功能. 1.1直接使用hadoop面临的问题 ...

  7. JavaSE打开windows文件

    第一个参数表示用什么程序打开,第二个参数表示文件的路径 例一: //用记事本打开d:/test.txt文件 Process p = java.lang.Runtime.getRuntime().exe ...

  8. SpringBoot学习:添加JSP支持

    项目下载地址:http://download.csdn.NET/detail/aqsunkai/9805821 (一)pom中添加依赖: <!-- https://mvnrepository.c ...

  9. 使用jenkins构建一个自由风格的项目

    一.创建一个freestyle风格的构建项目 二.输入任务名称和选择任务类型 三.配置项目 3.1:选择代码托管 3.2:到gitlab上去配置deploy key 3.3:到jenkins服务器去生 ...

  10. 哈希表 -数据结构(C语言实现)

    读数据结构与算法分析 哈希表 一种用于以常数平均时间执行插入.删除和查找操作的数据结构. 但是是无序的 一般想法 通常为一个包含关键字的具有固定大小的数组 每个关键字通过散列函数映射到数组中 冲突:两 ...