Java中栈、堆和常量池

Java内存分配主要包括如下几个区域:

寄存器

    最快的存储区, 由编译器根据需求进行分配,咱们在程序中没法控制.。html

    存放基本类型的变量数据和对象的引用(就是一个名字),对象自己不存放在栈中,而是存放在堆或者常量池中。栈内存归属于单个线程,每一个线程都会有一个栈内存,其存储的变量只能在其所属线程中可见,即栈内存能够理解成线程的私有内存。栈区内存由编译器自动分配释放,具体方法执行结束以后,系统自动释放JVM内存资源。java

    存放全部new出来的对象或数组。堆内存中的对象对全部线程可见,能够被全部线程访问。jvm不定时查看堆中的对象,若是没有引用指向这个对象就回收。数组

方法区

    只是JVM规范中定义的一个概念,用于存储类信息、常量池、静态变量、JIT编译后的代码等数据,具体放在哪里,不一样的实现能够放在不一样的地方。而永久代Hotspot虚拟机特有的概念,是方法区的一种实现,别的JVM都没有这个东西。    jvm

静态域

    存放静态成员(static定义的) 。spa

常量池

    存放字符串常量和基本类型常量(public static final)。线程

非RAM(随机存取存储器)存储

    硬盘等永久存储空间。code

    

    这里咱们主要关心栈,堆和常量池,对于栈和常量池中的对象能够共享,对于堆中的对象不能够共享。栈中的数据大小和生命周期是能够肯定的,当没有引用指向数据时,这个数据就会消失。堆中的对象的由垃圾回收器负责回收,所以大小和生命周期不须要肯定,具备很大的灵活性。 htm

1.声明和实例化

声明:A a=null ,声明一个A类的对象a,a放在栈中。对象

实例化:a=new A() ,实例化这个对象a,new A() 放在堆中。blog

2. String s=newString("a")和Strings=”a”建立了几个对象?

    String s= newString("a")建立了两个对象,一个是在常量池中,一个是在堆内存中,常量池的为"a",堆内存中为new String()。变量s指向该new string()对象,而该对象又指向在常量池中的字符串常量”a”。注意的是,在new的时候java虚拟机先去内存的常量池中查找”a”这个对象,若是有就不建立了,直接把堆中的对象指向该字符串。

    String s="a"的意思就是在栈中建立一个字符串类型的变量s,而且变量s直接指向常量池中的字符串对象”a”,省去了中间的堆内存中的对象。注意的是,String s = "a",这行代码被执行的时候,java虚拟机首先在字符串池中查找是否已经存在了值为"a"这么一个对象,它的判断依据是String类equals(Object obj)方法的返回值。若是有,则再也不建立新的对象,直接返回已存在对象的引用;若是没有,则先建立这个对象,而后把它加入到字符串池中,再将它的引用返回。

String s1=”china”

String s2=”china”

String s3=”england”

String s4=new String(“china”)

String s5=new String(“england”)

    对于字符串,其对象的引用(这里指:s1,s2,s3,s4,s5)都是存储在栈中的,若是是编译期已经建立好(直接用双引号定义的)的就存储在常量池中,若是是运行期new出来的(一旦new就会开辟新的堆内存)才存储在堆中。对于equals相等的字符串,在常量池中永远只有一份,在堆中有多份。

3. 数据存放位置

int s1=6;                         s1存放在栈中;6存放在常量池

char s2 = 'g';                    s2存放在栈中;'g'存放在常量池

boolean flag = true;              flag存放在栈中;true存放在常量池

byte b = 6;                       b存放在栈中;6存放在常量池

String s3 = "china";              s3存放在栈中;"china"存放在常量池

String s4= new String("abc");     s4存放在栈中;new String()存放在堆中;"abc"存放在常量池中

注意:

    栈(stack):主要保存基本类型(或者叫内置类型)(char、byte、short、int、long、float、double、boolean)和对象的引用,数据能够共享,速度仅次于寄存器(register),快于堆。 

相关文章
相关标签/搜索