转载自: http://www.cnblogs.com/aigongsi/archive/2012/04/06/2434771.html

java与C,c++有很大的不同就是java语言开发者不需要关注内存信息,不会显式的直接操作内存,而是通过jvm虚拟机来实现。

java虚拟机运行的时候内存分配图如下图:

jvm虚拟机栈:一个是线程独有的,每次启动一个线程,就创建一个jvm虚拟机栈,线程退出的时候就销毁。这里面主要保存线程本地变量名和局部变量值。

本地方法栈: 调用本地jni方法的时候而创建的。这里分配的jvm之外的内存空间。方法调用结束之后销毁。

pc寄存器 : 这个保存线程当前执行的字节码指令

堆:主要保存创建的对象。

方法区:保存class相关的信息。主要是class的一个内存结构信息

常量池:方法区的一部分,主要保存class内存结构中常量值 例如String值,public static final 类型的值

我们这里说的垃圾回收,主要是java虚拟机对堆内存区域的回收。

1 首先的问题是:jvm如何知道那些对象需要回收 ?

目前有两种算法

  • 引用计数法

每个对象上都有一个引用计数,对象每被引用一次,引用计数器就+1,对象引用被释放,引用计数器-1,直到对象的引用计数为0,对象就标识可以回收

这个可以用数据算法中的图形表示,对象A-对象B-对象C 都有引用,所以不会被回收,对象B由于没有被引用,没有路径可以达到对象B,对象B的引用计数就就是0,对象B就会被回收。

但是这个算法有明显的缺陷,对于循环引用的情况下,循环引用的对象就不会被回收。例如下图:对象A,对象B 循环引用,没有其他的对象引用A和B,则A和B 都不会被回收。

  • root搜索算法

这种算法目前定义了几个root,也就是这几个对象是jvm虚拟机不会被回收的对象,所以这些对象引用的对象都是在使用中的对象,这些对象未使用的对象就是即将要被回收的对象。简单就是说:如果对象能够达到root,就不会被回收,如果对象不能够达到root,就会被回收。

如下图:对象D访问不到根对象,所以就会被回收

以下对象会被认为是root对象:

  • 被启动类(bootstrap加载器)加载的类和创建的对象
  • jvm运行时方法区类静态变量(static)引用的对象
  • jvm运行时方法去常量池引用的对象
  • jvm当前运行线程中的虚拟机栈变量表引用的对象
  • 本地方法栈中(jni)引用的对象

由于这种算法即使存在互相引用的对象,但如果这两个对象无法访问到根对象,还是会被回收。如下图:对象C和对象D互相引用,但是由于无法访问根,所以会被回收。

jvm在确定是否回收的对象的时候采用的是root搜索算法来实现。

在root搜索算法的里面,我们说的引用这里都指定的是强引用关系。所谓强引用关系,就是通过用new 方式创建的对象,并且显示关联的对象

1
Object obj = new Object();

以上就是代表的是强引用关系,变量obj 强引用了 Object的一个对象。

java里面有四种应用关系,从强到弱分别为:

Strong Reference(强引用) –>Weak Reference (弱引用) -> Soft Reference(软引用) – > Phantom Reference(引用)

Strong Reference : 只有在引用对象root不可达的情况下才会标识为可回收,垃圾回收才可能进行回收

Weak Reference :即使在root算法中 其引用的对象root可达到,但是如果jvm堆内存 不够的时候,还是会被回收。

Soft Reference : 无论其引用的对象是否root可达,在响应内存需要时,由垃圾回收判断是否需要回收。

Phantom Reference :在回收器确定其指示对象可另外回收之后,被加入垃圾回收队列.

下面可以看一个测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public class ReferenceTest {
 
    public static final Map<Integer, Reference> map = new HashMap<Integer, Reference>();
 
    public static void main(String[] args) {
        for (int i = 0; i < 1000; i++) {
            map.put(i, new WeakReference(new ReferenceObject(i)));
        }
 
        int i = 0;
        for (Reference r : map.values()) {
            if (r.get() == null) {
                i++;
            }
        }
        System.out.println("被回收的对象数:" + i);
    }
 
    static class ReferenceObject {
        private int    i;
 
        private byte[] b;
 
        public ReferenceObject(int i) {
            this.i = i;
            b = new byte[1024 *10];
        }
    }
}

这里创建大约1000个 10K的 Weak Reference 对象,最后打印的结果是:被回收的对象数:767,这里ReferenceObject如果设置为1K的话,最后的打印结果是0

这个例子并不严谨,但是却说明了被Weak Reference的对象在一定的时候会被jvm回收,但是强引用就不会出现这种状态。

Java内存区域和判断对象“死”“活”算法的更多相关文章

  1. Java虚拟机2:Java内存区域及对象

    几个计算机的概念 为以后写文章考虑,也为巩固自己的知识和一些基本概念,这里要理清楚几个计算机中的概念. 1.计算机存储单位 从小到大依次为位Bit.字节Byte.千字节KB.兆M.千兆GB.TB,相邻 ...

  2. Java内存区域与对象创建过程

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

  3. Java内存区域和对象的创建

    文章绝大部分内存摘抄自<深入理解Java虚拟机>,结合了小部分个人理解如果有什么错误,还望指出,如果涉及到侵权,联系博主,立马删除,再次感谢<深入理解Java虚拟机>的作者-周 ...

  4. 《深入理解Java虚拟机》-----第2章 Java内存区域与内存溢出异常

    2.1 概述 对于从事C.C++程序开发的开发人员来说,在内存管理领域,他们即是拥有最高权力的皇帝又是执行最基础工作的劳动人民——拥有每一个对象的“所有权”,又担负着每一个对象生命开始到终结的维护责任 ...

  5. Java 内存区域和GC机制分析

    目录 Java垃圾回收概况 Java内存区域 Java对象的访问方式 Java内存分配机制 Java GC机制 垃圾收集器 Java垃圾回收概况 Java GC(Garbage Collection, ...

  6. Java 内存区域和GC机制

    目录 Java垃圾回收概况 Java内存区域 Java对象的访问方式 Java内存分配机制 Java GC机制 垃圾收集器 Java垃圾回收概况 Java GC(Garbage Collection, ...

  7. Java系列笔记(3) - Java 内存区域和GC机制

    目录 Java垃圾回收概况 Java内存区域 Java对象的访问方式 Java内存分配机制 Java GC机制 垃圾收集器 Java垃圾回收概况 Java GC(Garbage Collection, ...

  8. Java 内存区域和GC机制--备用

    Java垃圾回收概况 Java GC(Garbage Collection,垃圾收集,垃圾回收)机制,是Java与C++/C的主要区别之一,作为Java开发者,一般不需要专门编写内存回收和垃圾清理代 ...

  9. JAVA内存区域和GC机制

    目录 Java垃圾回收概况 Java内存区域 Java对象的访问方式 Java内存分配机制 Java GC机制 垃圾收集器 Java垃圾回收概况 Java GC(Garbage Collection, ...

随机推荐

  1. FastDFS配置说明

    前面了解了fastdfs的原理,接下来就熟悉一下安装过程,准备了三台机器,一台模拟client,一台模拟storage,一台模拟tracker.     三台机器均为debian6,系统为最小化安装, ...

  2. C# csv 操作类

    using System.Data; using System.IO; using System.Text; namespace YanZhiwei.DotNet2.Utilities.Common ...

  3. 6.1:SportStore:一个真实的应用

    之前的小例子让我们演示了AngularJS的一些特性,但他们缺少上下文.要解决这个问题,作者要创建一个简单单真实的电子商务应用. 作者将创建一个在线产品分类,客户可以通过分类和页面浏览,一个购物车用户 ...

  4. cocospod 安装和使用

    一 ruby 安装 要安装coocspod 首先需要安装ruby,可以先安装xcode,在安装macport 下载地址,最后执行命令 port install ruby 二.安装CocoaPods 1 ...

  5. Json常见问题

    1.创建包含 JSON 语法的 JavaScript 字符串: var txt = '{ "employees" : [' + '{ "firstName":& ...

  6. Postgres-XL集群搭建

    Postgres-XL 是一个完全满足ACID的.开源的.可方便进行水平扩展的.多租户安全的.支持share-nothing;支持海量数据并行处理-MPP(Massively Parallel Pro ...

  7. [团队项目] Scrum 项目 2.0 产品BACKLOG

    Scrum 项目 2.0 阅读教材第8章,8.1~8.3节 P157~168,了解获取用户需求的办法,每个组可以选择一二加以应用. 8.4节P168-171 查阅NABCDA模型的具体说明. 2.SC ...

  8. nodejs表单验证

    //创建express连接 var exp = require('xepress'), http = require('http'); //初始化exprerss模块 var app = exp(); ...

  9. MessageFlood 分类: 串 2015-06-18 17:00 10人阅读 评论(0) 收藏

    MessageFlood TimeLimit: 1500ms Memory limit: 65536K 有疑问?点这里^_^ 题目描述 Well,how do you feel about mobil ...

  10. oracle驱动地址

    D:\app\LHComputer\product\12.1.0\dbhome_1\ODP.NET\bin\2.x