Java-内存结构

原创 2016年06月02日 11:10:23

内存泄露是什么?

内存泄露的定义:

当某些对象不再被应用程序所使用,但是由于仍然被引用而导致垃圾收集器不能释放(Remove,移除)他们.
用白话来说就是: 该回收的内存没被回收,最后因为内存不够用而导致程序报错。

要理解这个定义,我们需要理解内存中的对象状态.

下图展示了什么是不使用的部分,以及未被引用的部分:
这里写图片描述

从图中可以看出,内存中存在着 有引用的对象,和无引用的对象. 无引用的对象将被垃圾收集器所回收,而有引用的对象则不会被当做垃圾收集. 因为没有任何其他对象所引用,所以无引用对象一定是不再使用的。 但是有一部分无用对象仍然被(无意中)引用着。这就是发生内存泄露的根源.

Java 内存分配策略

Java 程序运行时的内存分配策略有三种:
1. 静态分配—静态存储区(也称方法区)
2. 栈式分配—栈区
3. 堆式分配—堆区

静态存储区(方法区):主要存放静态数据、全局 static 数据和常量。这块内存在程序编译时就已经分配好,并且在程序整个运行期间都存在。

栈区 :当方法被执行时,方法体内的局部变量都在栈上创建,并在方法执行结束时这些局部变量所持有的内存将会自动被释放。因为栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。

堆区 : 又称动态内存分配,通常就是指在程序运行时直接 new 出来的内存。这部分内存在不使用时将会由 Java 垃圾回收器来负责回收。

栈与堆的区别:

在方法体内定义的(局部变量)一些基本类型的变量和对象的引用变量都是在方法的栈内存中分配的。当在一段方法块中定义一个变量时,Java 就会在栈中为该变量分配内存空间,当超过该变量的作用域后,该变量也就无效了,分配给它的内存空间也将被释放掉,该内存空间可以被重新使用。

堆内存用来存放所有由 new 创建的对象(包括该对象其中的所有成员变量)和数组。在堆中分配的内存,将由 Java 垃圾回收器来自动管理。在堆中产生了一个数组或者对象后,还可以在栈中定义一个特殊的变量,这个变量的取值等于数组或者对象在堆内存中的首地址,这个特殊的变量就是我们上面说的引用变量。我们可以通过这个引用变量来访问堆中的对象或者数组。
举个例子:

public class Sample() {
     int s1 = 0;
     Sample mSample1 = new Sample();

     public void method() {
          int s2 = 1;
          Sample mSample2 = new Sample();
     }
}

Sample mSample3 = new Sample();
Sample 类的局部变量 s2 和引用变量 mSample2 都是存在于栈中,但 mSample2 指向的对象是存在于堆上的。

mSample3 指向的对象实体存放在堆上,包括这个对象的所有成员变量 s1 和 mSample1,而它自己存在于栈中。
结论:

局部变量的基本数据类型和引用存储于栈中,引用的对象实体存储于堆中。—— 因为它们属于方法中的变量,生命周期随方法而结束。

成员变量全部存储与堆中(包括基本数据类型,引用和引用的对象实体)—— 因为它们属于类,类对象终究是要被new出来使用的。

Java是如何管理内存

Java的内存管理就是对象的分配和释放问题。在 Java 中,程序员需要通过关键字 new 为每个对象申请内存空间 (基本类型除外),所有的对象都在堆 (Heap)中分配空间。另外,对象的释放是由 GC 决定和执行的。在 Java 中,内存的分配是由程序完成的,而内存的释放是由 GC 完成的,这种收支两条线的方法确实简化了程序员的工作。但同时,它也加重了JVM的工作。这也是 Java 程序运行速度较慢的原因之一。因为,GC 为了能够正确释放对象,GC 必须监控每一个对象的运行状态,包括对象的申请、引用、被引用、赋值等,GC 都需要进行监控。

监视对象状态是为了更加准确地、及时地释放对象,而释放对象的根本原则就是该对象不再被引用。

为了更好理解 GC 的工作原理,我们可以将对象考虑为有向图的顶点,将引用关系考虑为图的有向边,有向边从引用者指向被引对象。另外,每个线程对象可以作为一个图的起始顶点,例如大多程序从 main 进程开始执行,那么该图就是以 main 进程顶点开始的一棵根树。在这个有向图中,根顶点可达的对象都是有效对象,GC将不回收这些对象。如果某个对象 (连通子图)与这个根顶点不可达(注意,该图为有向图),那么我们认为这个(这些)对象不再被引用,可以被 GC 回收。

以下,我们举一个例子说明如何用有向图表示内存管理。对于程序的每一个时刻,我们都有一个有向图表示JVM的内存分配情况。以下右图,就是左边程序运行到第6行的示意图。

版权声明:本文为博主原创文章,未经博主允许不得转载。

Java虚拟机详解----JVM内存结构

http://www.cnblogs.com/smyhvae/p/4748392.htm 主要内容如下: JVM启动流程JVM基本结构内存模型编译和解释运行的概念   ...
  • bluetjs
  • bluetjs
  • 2016年10月20日 17:10
  • 7259

Java 对象在堆中的内存结构

翻译人员: 铁锚 翻译日期: 2013年11月8日 原文链接:  What do Java objects look like in memory during run-time? 我们知道,函数每...
  • renfufei
  • renfufei
  • 2013年11月09日 19:09
  • 20573

JVM体系结构-----深入理解内存结构

一、概述        内存在计算机中占据着至关重要的地位,任何运行时的程序或者数据都需要依靠内存作为存储介质,否则程序将无法正常运行。与C和C++相比,使用Java语言编写的程序并不需要显示的为每...
  • ljheee
  • ljheee
  • 2016年08月17日 00:42
  • 2353

Java内存结构

  • 2014年10月08日 16:47
  • 34KB
  • 下载

Java内存结构.pdf

  • 2011年11月26日 21:14
  • 396KB
  • 下载

java对象在内存中的结构

  • 2011年05月05日 15:50
  • 31KB
  • 下载

传智播客_Java基础_Java内存结构

  • 2014年01月05日 17:11
  • 100KB
  • 下载

Java千百问_06数据结构(016)_引用类型数组在内存中如何储存

点击进入_更多_Java千百问1、存放基本类型数组在内存中如何储存了解什么是数组看这里:java中的数组是什么 了解数组在内存中的储存看这里:java数组如何存储在内存中 java的数组中可以存放...
  • ooppookid
  • ooppookid
  • 2016年05月14日 13:27
  • 3965

JAVA之旅(三)——数组,堆栈内存结构,静态初始化,遍历,最值,选择/冒泡排序,二维数组,面向对象思想

JAVA之旅(三)——数组,堆栈内存结构,静态初始化,遍历,最值,选择/冒泡排序,二维数组,面向对象思想 我们继续JAVA之旅 一.数组1.概念 数组就是同一种类型数据的集合,就是一个容器数组...
  • qq_26787115
  • qq_26787115
  • 2016年05月14日 17:39
  • 4036

Java 对象在堆中的内存结构

翻译人员: 铁锚 翻译日期: 2013年11月8日 原文链接:  What do Java objects look like in memory during run-time? 我们知道,函数每...
  • renfufei
  • renfufei
  • 2013年11月09日 19:09
  • 20573
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Java-内存结构
举报原因:
原因补充:

(最多只允许输入30个字)