您的位置:首页 > 编程语言 > Java开发

java基础--运行时数据区的小结

2013-11-08 18:12 302 查看
  java的内存分配这一块对我来说一直都是比较头疼的内容,想学也不知道该何从下手,偶然间在osc上看到一篇相关介绍的文章,文章也是对其他技术博客的一些总结并提供的博客地址,于是也看了看那些技术大牛的博客,高上大的感脚 ;-P .于是打算一步一步来,首先是对虚拟机的运行时数居区的一点点总结。ps:由于当时只是做了一些摘抄,下面都是根据当时的一些摘抄总结的,所以可能由于时间原因记得有失偏颇,如有错误还望指正。;-)
  当一个java程序运行的时候,比如CMD下用java命令运行一个.class文件,或者在Eclipse下Run as ,都有一个虚拟机随之启动,当java程序结束,虚拟机也随之结束了。虚拟机为java程序提供了一个运行时数据区来存储各种数据:



下面分别来说说数据区各区域的作用。
栈:存放基本类型的数据和对象的引用。保存该线程中函数调用的相关数据,包括方法的局部变量,被调用时传进来的参数返回值以及运算的中间结果等。栈和寄存器是被线程所私有的,不能被其他线程访问,因此不需要考虑多线程情况下栈数据的访问同步问题。另外,存在栈中的数据可被共享,比如
int i = 3;这条语句会现在栈中查询是否存在3这个值,否则创建这个值,当另一条语句  int j = 3;执行时,就不会再创建新值,而是和 i 共享。
栈的优势:存取速度比堆快,仅次于寄存器。
栈的缺点:存于栈中的数据大小与生命周期必须是确定的。
对于栈可以这样理解:栈是操作系统在建立某个进程或线程时为这个线程建立的存储区域。它是一种先进后出的数据结构。

堆:存放new产生的数据。堆中的数据由垃圾回收机制(GC)来负责处理。堆中的数据由虚拟机下的所有线程所共享。
堆的优势:可以动态地分配内存大小,对象的生存周期也不必事先明确,java回收机制会自动将不再使用的数据进行回收,释放空间。
堆的缺点:由于是动态非配内存,所以存取速度比较慢。

方法区:又叫静态区。方法区和堆中数据有虚拟机的所有线程所共享,当装载一个字节码文件时,会从字节码文件的二进制数据中解析类型都信息,然后将信息保存在方法区中。类的静态变量,成员字段域,方法和构造函数也保存在方法区中。
虚拟机会将装载的类的以下信息保存在方法区中:

这个类型的全限定名
这个类型的直接超类的全限定名(除非直接超类是Object)
这个类型是类类型还是接口类型
这个类型的访问修饰符
任何直接超类接口的全限定名的有序列表

常量池:在编译时期被确定,并被保存在已编译的.class文件中的一些数据。程序运行时,常量池存储在方法区中,通常包含代码中定义的各种基本类型对象型(String,数组)常量值(final)

下面是根据小结的理解写的一个例子,如有理解有变差或者代码有不对的地方还望指出:

public class RunTimeDataAreaDemo {
    //final修饰的常量,保存在方法区的常量池。
    final int finite = 80;
    //静态变量保存在方法区中
    static int count = 100;
    //构造函数也在方法区中
    public RunTimeDataAreaDemo() {}
    public static void main(String[] args) {
        //编译时期确定的值保存在常量池
        String str = "hello world!!";
        method(str);
        //java的传参传的是引用的拷贝,由于String是不可变类型,在
        //函数中str的真身和拷贝都指向同一个块内存区域,当改变引用拷贝的值时,
        //实际上是指向了一个新的String对象,所以输出真身的值还是原来的值。
        System.out.println(str);//hello
world!!
        Person p = new Person("bill", 50);
        method(p);
        //p的真身和拷贝都指向同一个块内存区域,当改变引用拷贝的值时,
        //真身和拷贝的指向没有变,所以输出真身的值的时候是改变后的值。
        System.out.println(p.name + "__" + p.age);//tom__40
    }
    //方法保存在方法区
    public static void method(String str){
        //传进来的参数保存在栈中
        str = "goodbye world!!";
    }
    //方法保存在方法区
    public static void method(Person p){
        p.name = "tom";
        p.age = 40;
    }
}
class Person{
    String name;
    int age;
    Person(String name,int age){
        this.name = name;
        this.age = age;
    }
}

java中方法参数的引用传递(大牛的博客截图):

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息