java对象创建与内存模型总结

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java对象创建与内存模型总结相关的知识,希望对你有一定的参考价值。

 1、JVM管辖的内存大致分为三个逻辑部分:java栈(Heap)、java堆(JavaStack)和方法区(MethodArea)。在JVM启动时创建,关闭时全部回收。


     栈、本地方法栈、程序计数器:以线程为粒度,每个线程拥有自己的部分。而堆和方法区被所有线程共享。
     堆:运行时的数据区域,程序(线程)运行时动态分配。
     方法区:静态存储区,存储被装载到JVM中的class信息。

 


2、栈

    i)、存放基本类型的变量数据和对象的引用变量(变量本身存放在堆和常量池中)。
    ii)、java系统必须知道存储在栈内所有项的确切生命周期(故变量的垃圾回收由系统处理),以便上下移动栈指针,相比堆更高效,但限制了程序的灵活性。
    iii)、可以数据共享(共享的是值,改变一个变量不会影响另一个变量)
        int c = 1;int d =1;//c,d共享栈数据1
        d = 2;//如果栈中没有2这个值(如果有就直接引用共享),新建值并将d重新指向它。


3、堆

    i)、存放由new操作符创建的对象和数组(‘可以但不必须’将其引用存放在栈中,方便快速访问)。
    ii)、运行时动态分配内存(速度慢于栈的主要原因),并由gc管理。
    iii)、堆中的垃圾回收由gc处理(用户不能干预,即便调用System.gc()也只是‘希望执行’垃圾回收。因为gc是为所有java应用进程服务且gc的执行会影响所有java应用进程,不特殊对待某个进程)。



4、方法区

    i)、位于堆上的静态存储区,存储被装载到JVM中的class信息。

    ii)、常量池: 每个常量池从方法区分配,存放类、方法、接口等中的常量和字符串常量(常量:public static final)。
            每个常量池在编译期确定下来,并保存到.class文件中。
            可以数据共享。



5、特殊的String对象
    String a1 = "123"; //这一句创建了1个字符串常量对象(常量池中)。
    String a2 = "123"; //这两句还是1个对象。a2也指向a1的字符串常量对象“123”。

    String b1 = new String("123"); //这一句本身应该创建两个对象(先创建常量对象“123”,再用它做参数用new在堆中创建一个新对象)。但因为字符串常量对象“123”已存在(常量池),所以此时只创建1个对象(堆中)
    String b2 = new String("123"); //此时因为“123”已存在常量池中,故只用new操作符新建一个对象。

    System.out.println(a1 == a2); //运算符 == 比较引用地址
    System.out.println(b1 == b2);

    对于 "123"           --在常量池中创建字符串常量对象“123”(如果常量池中已有该对象就直接引用而不再创建)。共一个对象,位于常量池中。
    对于 new String("123")       --先在常量池中创建字符串常量对象“123”,再在堆中用new操作符创建新对象(new操作符每次都新建不同内存地址的对象)。共两个对象,分别存储于常量池、堆中。

 


6、垃圾回收

    i)、处理位于java逻辑堆上的垃圾对象。

    ii)、采用基于“标记-清除”、“停止-复制”算法的“自适应”的垃圾回收技术。进行垃圾回收时会暂停程序的运行。

    iii)、当对象失去所有引用成为垃圾后,可能不被垃圾回收。

    iiii)、无论“垃圾回收”还是“终结”,都不保证能发生,如果JVM并未面临内存耗尽的情形,它是不会浪费时间去执行垃圾回收以回复内存。

    iiiii)、finalize()正确用法是,在对象即将被回收时,用来做一些善后处理。

    iiiiii)、System.gc()用于强制进行垃圾回收动作。但并不能保证垃圾回收动作的执行,顶多增加垃圾回收动作发生的可能性。垃圾回收动作不受用户干预,因为gc服务于JVM中的所有进程,不为某个进程特殊处理。

 

      int[] ary = {1,2,3}; //当ary超过作用域后,变量ary将立即在栈中被系统回收并可另作他用。它所指向的数组对象被gc‘标记-清除’,但对象依然存在堆中,等到一个(不确定)时间被gc回收。

 


6、对象创建的总结

    java栈用来存放基本类型的变量数据和对象的引用变量,但不存放对象内容;
    java堆存放使用new关键字创建的对象和数组对象;
    特殊情况是字符串这个包装类:其引用是存放在栈里的,而对象内容位置由创建方式来决定(常量池、堆),用“”在编译期创建的存放在字符串常量池中,用new操作符在运行时创建的存放在堆中。








































以上是关于java对象创建与内存模型总结的主要内容,如果未能解决你的问题,请参考以下文章

深入理解Java虚拟机Java内存区域模型对象创建过程常见OOM

Java内存模型(JMM)总结与学习

JVM内存模型Java内存模型 和 Java对象模型

JVM内存模型及String对象内存分配

JVM内存模型总结

Java并发编程-JMM内存模型与volatile关键字