Java的内存机制

转载 2013年12月04日 22:04:13

参考:http://www.j2megame.org/index.php/content/view/2246/125.html

1.Java的内存机制

 Java 把内存划分成两种:一种是栈内存,另一种是堆内存。在函数中定义的一些基本类型的变量对象的引用变量都是在函数的栈内存中分配,当在一段代码块定义一个变量时,Java 就在栈中为这个变量分配内存空间,当超过变量的作用域比如,在函数A中调用函数B,在函数B中定义变量a,变量a的作用域只是函数B,在函数B运行完以后,变量a会自动被销毁。分配给它的内存会被回收,Java 会自动释放掉为该变量分配的内存空间,该内存空间可以立即被另作它用。

  堆内存用来存放由 new 创建的对象和数组,在堆中分配的内存,由 Java 虚拟机的自动垃圾回收器来管理。在堆中产生了一个数组或者对象之后,还可以在栈中定义一个特殊的变量,让栈中的这个变量的取值等于数组或对象在堆内存中的首地址,栈中的这个变量就成了数组或对象的引用变量,以后就可以在程序中使用栈中的引用变量来访问堆中的数组或者对象,引用变量就相当于是为数组或者对象起的一个名称。引用变量是普通的变量,定义时在栈中分配,引用变量在程序运行到其作用域之外后被释放。而数组和对象本身在堆中分配,即使程序运行到使用 new 产生数组或者对象的语句所在的代码块之外,数组和对象本身占据的内存不会被释放,数组和对象在没有引用变量指向它的时候,才变为垃圾,不能在被使用,但仍然占据内存空间不放,在随后的一个不确定的时间被垃圾回收器收走(释放掉)。这也是 Java 比较占内存的原因,实际上,栈中的变量指向堆内存中的变量,这就是 Java 中的指针!

代码实例Test01:单个对象创建

复制代码
class Person{
String name;
int age;
public void tell(){
System.out.println("姓名:"+name+"年龄"+age);
}
}

public class Test01 {
public static void main(String[] args) {
Person per=new Person();
}
}
复制代码

在上述程序中实例化了一个对象per,在实例化对象的过程中需要在内存中开辟空间,这其中就包括栈内存和对内存。具体的内存分配如下图所示:

我们可以从上图中发现,对象名称per被保存在了栈内存中(更加准确的说法是,在栈内存中保存的是堆内存空间的访问地址),而对象的具体内容,比如属性name和age,被保存在了堆内存中。因为per对象只是被实例化,还没有具体被赋值,所以都是默认值。字符串的默认值为null,int类型的默认值为0。前面也已经提到,堆内存空间必须使用new关键字才能开辟。

代码实例Test02:多个对象创建

复制代码
class Person{
String name;
int age;
public void tell(){
System.out.println("姓名:"+name+",年龄:"+age);
}
}

public class Test02 {
public static void main(String[] args) {
Person per1=new Person();
Person per2=new Person();

per1.name="张三";
per1.age=30;
per2.name="李四";
per2.age=33;

per1.tell();
per2.tell();
}
}
复制代码

关键概念:类跟数组一样,都是属于引用类型,引用类型就是指一堆对内存可以同时被多个栈内存指向。下面来看一下引用传递的简单实例。

代码实例Test03:对象引用传递1

复制代码
class Person{
String name;
int age;
public void tell(){
System.out.println("姓名:"+name+",年龄:"+age);
}
}

public class Test03{
public static void main(String[] args) {
Person per1=new Person();
Person per2=per1;

per1.name="张三";
per1.age=30;
per2.age=33;

per1.tell();
per2.tell();
}
}
复制代码

程序运行结果为:

姓名:张三,年龄:33
姓名:张三,年龄:33

从程序的运行结果可以发现,两个对象输出的内容一样,实际上所谓的引用传递,就是将一个堆内存空间的使用权交个多个栈内存空间,每个栈内存空间都可以修改堆内存空间的内容,此程序的内存分配图如下所示:

注意:上述实例中对象per2没有堆内存空间,这是因为对象per2只进行了声明操作,也没有进行实例化操作。只有使用new关键字实例化以后才会有对内存空间。

代码实例Test04:对象引用传递2

复制代码
class Person{
String name;
int age;
public void tell(){
System.out.println("姓名:"+name+",年龄:"+age);
}
}

public class Test04 {
public static void main(String[] args) {
Person per1=new Person();
Person per2=new Person();

per1.name="张三";
per1.age=30;
per2.name="李四";
per2.age=33;
per2=per1;

per1.tell();
per2.tell();
}
}
复制代码

上述程序运行结果为:

姓名:张三,年龄:30
姓名:张三,年龄:30

从程序的输出结果可以发现可Test03一样。不过内存分配发生了一些变化,具体如下所示:

注意点:

  1. Java本身提供垃圾收集机制(Garbage Collection,GC),会不定期施放不用的内存空间,只要对象不用了,就会等待GC释放空间,如上面堆内存中的name="李四";age=33。
  2. 一个栈内存只能指向一个对内存空间,如果要想再指向其他的堆内存空间,则必须先断开已有的指向才能分配新的指向。

 

源文件《http://www.cnblogs.com/xwdreamer/archive/2012/04/01/2428857.html

 

 

在任何编程语言中,无论是基本类型还是引用类型,不论其作用域如何,都必须为其分配一定的内存空间,Java语言也不例外,Java的数据类型可以分为两种:基本类型(变量持有数据本身的值)和引用类型(是某个对象的引用,而并非是对象本身);基本类型包括:boolean、float、double、int、long、short、byte以及char;在Java编程语言中除基本类型以外其余都是引用类型如:类类型、数组类型等。

在计算机内存中主要来自四个地方:heap segment(堆区)、stacksegment(栈区)、codesegment(代码区)、data segment(数据区);不同的地方存放不同数据:其中堆区主要存放Java程序运行时创建的所有引用类型都放在其中;栈区主要存放Java程序运行时所需的局部变量、方法的参数、对象的引用以及中间运算结果等数据;代码区主要存放Java的代码;数据区主要存放静态变量及全局变量;以下结合实例来探讨其具体机制。

class Student {

 private String name;

 private int age;

 public Student(String name, int age) {

  this.name = name;

  this.age = age;

 }

}

public class Test {

 static int i = 10;

 public static voidmain(String[] args) {

  Student s1 = newStudent(“feng”, 21);

 }

}

当该程序运行起来后,其计算机内存分布大致如下:

对象在内部表示Java虚拟机规范并没有规定其在堆中是如何表示的。对象的内部的表示会直接影响到堆区的设计以及垃圾收集器(GC)的设计。

Java在堆中的表示方法具体有两种:

把堆分成两个部分:一个句柄池,一个对象池;表示如下图所示:

用对象指针直接指向一组数据,而该数据包括对象实例数据以及指向方法区中的数据的指针,具体如下图所示:

小结:通过对对象内存分配的分析,来使读者对Java的底层有一个比较理性的认识,从而进一步掌握Java的基础知识。在深入了解了Java内存的分配以后,才能为以后编写高质量的程序打下坚实的基础,而且可以借鉴该思想来分析其它面向对象语言的内存分配问题。

 

源文档 <http://www.spasvo.com/news/html/2012123100627.html>

 

 

Java中内存运行机制解析

本文将由浅入深详细介绍Java内存分配的原理,以帮助新手更轻松的学习Java。这类文章网上有很多,但大多比较零碎。本文从认知过程角度出发,将带给读者一个系统的介绍。 进入正题前首先要知道的是Ja...
  • lyh20093867
  • lyh20093867
  • 2017年04月25日 12:42
  • 686

浅析Java中的内存机制

一.对象和引用 要了解Java中对象在内存中的位置,首先要分清楚两个概念,对象和引用。在Java中,使用new Object()来产生一个新的对象,这时,对象存在于堆内存中。而使用Object obj...
  • sinat_34260423
  • sinat_34260423
  • 2016年11月26日 20:01
  • 242

JVM内存管理及GC机制

一、概述Java GC(Garbage Collection,垃圾收集,垃圾回收)机制,是Java与C++/C的主要区别之一,作为Java开发者,一般不需要专门编写内存回收和垃圾清理代码,对内存泄露和...
  • suifeng3051
  • suifeng3051
  • 2015年09月08日 16:28
  • 10637

多态机制原理解析--从内存角度分析

回头看多态,又有了新的认识。 理解多态主要搞清楚以下几个问题就可以了:(以父类Pet,子类Dog为例) 1.为什么可以用表达式 Pet p1= new Dog(); //为什么可以用父类的引用指向...
  • csp277
  • csp277
  • 2015年11月10日 14:59
  • 839

【Java】内存机制详解(new操作的执行原理)

1.Java的内存机制  Java 把内存划分成两种:一种是栈内存,另一种是堆内存。在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配,当在一段代码块定义一个变量时,Java ...
  • yjqyyjw
  • yjqyyjw
  • 2016年10月17日 11:20
  • 1133

Java的内存分配机制(初步整理)

Java程序是运行在Java虚拟机(Java Virtual Machine,JVM)上的,可以把JVM理解为Java程序和操作系统之间的桥梁,JVM实现了Java的跨平台,Java内存分配原理一切都...
  • gaosure
  • gaosure
  • 2017年03月01日 08:07
  • 238

C++ 内存管理机制

zhuanz 内存管理是C++最令人切齿痛恨的问题,也是C++最有争议的问题,C++高手从中获得了更好的性能,更大的自由,C++菜鸟的收获则是一遍一遍的检查代码和对C++的痛恨,但内存管理在C+...
  • w_y_x_2001
  • w_y_x_2001
  • 2014年04月04日 08:36
  • 1087

Java的内存回收机制详解

Java的内存回收机制详解 说到java内存回收机制,就得先说内存回收的意义。 1 垃圾回收的意义 在C++中,对象所占的内存在程序结束运行之前一直被占用,在明确释放之前不...
  • YQlakers
  • YQlakers
  • 2017年04月12日 08:56
  • 956

java内存机制

优化应用程序代码的内存使用并不是一个新主题,但是人们通常并没有很好地理解这个主题。本文将简要介绍 Java 进程的内存使用,随后深入探讨您编写的 Java 代码的内存使用。最后,本文将展示提高代码内存...
  • xinlvye
  • xinlvye
  • 2013年09月04日 09:54
  • 435

java 内存机制

Java程序运行在JVM上,可以把JVM理解成Java程序和操作系统之间的桥梁,JVM实现了Java的平台无关性,由此可见JVM的重要性。所以在学习Java内存分配原理的时候一定要牢记这一切都是在JV...
  • u014223536
  • u014223536
  • 2015年03月05日 15:55
  • 282
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Java的内存机制
举报原因:
原因补充:

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