java各变量的存储位置
2015-10-07 16:19
323 查看
1.寄存器:最快的存储区, 由编译器根据需求进行分配,我们在程序中无法控制.
2. 栈:存放基本类型的变量数据和对象的引用,但对象本身不存放在栈中,而是存放在堆(new
出来的对象)或者常量池中(字符串常量对象存放在常量池中。)
3. 堆:存放所有new出来的对象。
4.
静态域:存放静态成员(static定义的)
5.
常量池:存放字符串常量和基本类型常量(public static
final)。
6.
非RAM存储:硬盘等永久存储空间
String s = new String(“xyz”);产生几个对象?一个或两个,如果常量池中原来没有”xyz”,就是两个。 先产生XYZ,再创建S
栈:包括java虚拟机栈(传统意义的栈)与本地方法栈。这里介绍java虚拟机栈:存放基本类型的变量数据、动态链接、方法出口、对象的引用等,但对象本身不存放在栈中,而是存放在堆(new
出来的对象)或者常量池中。
当在一段代码块定义一个变量时,Java就在栈中 为这个变量分配内存空间,当该变量退出该作用域后,Java会自动释放掉为该变量所分配的内存空间,该内存空间可以立即被另作他用。栈中的数据大小和生命周期是可以确定的,当没有引用指向数据时,这个数据就会消失。
堆:内存用来存放由new创建的对象和数组。
在堆中分配的内存,由Java虚拟机的自动垃圾回收器来管理。方法中的局部变量使用final修饰后,也是放在堆中,而不是栈中(注意final修饰的字符串常量除外)。
方法区(又称静态存储区):用于存储已被虚拟机加载的类信息、常量、静态变量、编译后的代码等数据。包括静态域、常量池等。其中静态域存放的是 static
定义的变量;常量池存放字符串常量、public static
final修饰的基本类型常量。
堆与栈
这里我们主要关心栈,堆和常量池,对于栈和常量池中的对象可以共享,对于堆中的对象不可以共享。栈中的数据大小和生命周期是可以确定的,当没有引用指向数据时,这个数据就会消失。堆中的对象的由垃圾回收器负
4000
责回收,因此大小和生命周期不需要确定,具有很大的灵活性,但缺点是,由于要在运行时动态
分配内存,存取速度较慢。
栈的优势是,存取速度比堆要快,仅次于寄存器,栈数据可以共享。但缺点是,存在栈中的数据大小与生存期必须是 确定的,缺乏灵活性。栈中主要存放一些基本类型的变量数据(int, short, long, byte, float, double, boolean, char)和对象句柄(引用)。
栈有一个很重要的特殊性,就是存在栈中的数据可以共享。假设我们同时定义:
Java代码
int a = 3;
int b = 3;
编译器先处理int a = 3;首先它会在栈中创建一个变量为a的引用,然后查找栈中是否有3这个值,如果没找到,就将3存放进来,然后将a指向3。接着处理int b = 3;在创建完b的引用变量后,因为在栈中已经有3这个值,便将b直接指向3。这样,就出现了a与b同时均指向3的情况。另外注意这里的a是一个指向int类型的引用,指向3这个字面值,这些字面值的数据,由于大小可知,生存期可知(这些字面值定义在某个程序块里面,程序块退出后,字段值就消失了),出于追求速度的原因,就存在于栈中,也就是说字面值3存储在栈中。
这时,如果再令 a=4;那么编译器会重新搜索栈中是否有4值,如果没有,则将4存放进来,并令a指向4;如果已经有了,则直接将a指向这个地址。因此a值的改变不会影响 到b的值。
要注意这种数据的共享与两个对象的引用同时指向一个对象的这种共享是不同的,因为这种情况a的修改并不会影响到b, 它是由编译器完成的,它有利于节省空间。而一个对象引用变量修改了这个对象的内部状态,会影响到另一个对象引用变量。
Java代码
1.int i1 = 9;
2.int i2 = 9;
3.int i3 = 9;
4.public static final int INT1 = 9;
5.public static final int INT2 = 9;
6.public static final int INT3 = 9;
对于成员变量和局部变量:成员变量就是方法外部,类的内部定义的变量;局部变量就是方法或语句块内部定义的变量。局部变量必须初始化。
形式参数是局部变量,局部变量的数据存在于栈内存中。栈内存中的局部变量随着方法的消失而消失。
成员变量存储在堆中的对象里面,由垃圾回收器负责回收。
常量池 (constant pool)
常量池指的是在编译期被确定,并被保存在已编译的.class文件中的一些数据。除了包含代码中所定义的各种基本类型(如int、long等等)和对象型(如String及数组)的常量值(final)还包含一些以文本形式出现的符号引用,比如:
◆类和接口的全限定名;
◆字段的名称和描述符;
◆方法和名称和描述符。
如果是编译期已经创建好(直接用双引号定义的)的就存储在常量池中,如果是运行期(new出来的)才能确定的就存储在堆中。对于equals相等的字符串,在常量池中永远只有一份,在堆中有多份。
2. 栈:存放基本类型的变量数据和对象的引用,但对象本身不存放在栈中,而是存放在堆(new
出来的对象)或者常量池中(字符串常量对象存放在常量池中。)
3. 堆:存放所有new出来的对象。
4.
静态域:存放静态成员(static定义的)
5.
常量池:存放字符串常量和基本类型常量(public static
final)。
6.
非RAM存储:硬盘等永久存储空间
String s = new String(“xyz”);产生几个对象?一个或两个,如果常量池中原来没有”xyz”,就是两个。 先产生XYZ,再创建S
栈:包括java虚拟机栈(传统意义的栈)与本地方法栈。这里介绍java虚拟机栈:存放基本类型的变量数据、动态链接、方法出口、对象的引用等,但对象本身不存放在栈中,而是存放在堆(new
出来的对象)或者常量池中。
当在一段代码块定义一个变量时,Java就在栈中 为这个变量分配内存空间,当该变量退出该作用域后,Java会自动释放掉为该变量所分配的内存空间,该内存空间可以立即被另作他用。栈中的数据大小和生命周期是可以确定的,当没有引用指向数据时,这个数据就会消失。
堆:内存用来存放由new创建的对象和数组。
在堆中分配的内存,由Java虚拟机的自动垃圾回收器来管理。方法中的局部变量使用final修饰后,也是放在堆中,而不是栈中(注意final修饰的字符串常量除外)。
方法区(又称静态存储区):用于存储已被虚拟机加载的类信息、常量、静态变量、编译后的代码等数据。包括静态域、常量池等。其中静态域存放的是 static
定义的变量;常量池存放字符串常量、public static
final修饰的基本类型常量。
堆与栈
这里我们主要关心栈,堆和常量池,对于栈和常量池中的对象可以共享,对于堆中的对象不可以共享。栈中的数据大小和生命周期是可以确定的,当没有引用指向数据时,这个数据就会消失。堆中的对象的由垃圾回收器负
4000
责回收,因此大小和生命周期不需要确定,具有很大的灵活性,但缺点是,由于要在运行时动态
分配内存,存取速度较慢。
栈的优势是,存取速度比堆要快,仅次于寄存器,栈数据可以共享。但缺点是,存在栈中的数据大小与生存期必须是 确定的,缺乏灵活性。栈中主要存放一些基本类型的变量数据(int, short, long, byte, float, double, boolean, char)和对象句柄(引用)。
栈有一个很重要的特殊性,就是存在栈中的数据可以共享。假设我们同时定义:
Java代码
int a = 3;
int b = 3;
编译器先处理int a = 3;首先它会在栈中创建一个变量为a的引用,然后查找栈中是否有3这个值,如果没找到,就将3存放进来,然后将a指向3。接着处理int b = 3;在创建完b的引用变量后,因为在栈中已经有3这个值,便将b直接指向3。这样,就出现了a与b同时均指向3的情况。另外注意这里的a是一个指向int类型的引用,指向3这个字面值,这些字面值的数据,由于大小可知,生存期可知(这些字面值定义在某个程序块里面,程序块退出后,字段值就消失了),出于追求速度的原因,就存在于栈中,也就是说字面值3存储在栈中。
这时,如果再令 a=4;那么编译器会重新搜索栈中是否有4值,如果没有,则将4存放进来,并令a指向4;如果已经有了,则直接将a指向这个地址。因此a值的改变不会影响 到b的值。
要注意这种数据的共享与两个对象的引用同时指向一个对象的这种共享是不同的,因为这种情况a的修改并不会影响到b, 它是由编译器完成的,它有利于节省空间。而一个对象引用变量修改了这个对象的内部状态,会影响到另一个对象引用变量。
Java代码
1.int i1 = 9;
2.int i2 = 9;
3.int i3 = 9;
4.public static final int INT1 = 9;
5.public static final int INT2 = 9;
6.public static final int INT3 = 9;
对于成员变量和局部变量:成员变量就是方法外部,类的内部定义的变量;局部变量就是方法或语句块内部定义的变量。局部变量必须初始化。
形式参数是局部变量,局部变量的数据存在于栈内存中。栈内存中的局部变量随着方法的消失而消失。
成员变量存储在堆中的对象里面,由垃圾回收器负责回收。
常量池 (constant pool)
常量池指的是在编译期被确定,并被保存在已编译的.class文件中的一些数据。除了包含代码中所定义的各种基本类型(如int、long等等)和对象型(如String及数组)的常量值(final)还包含一些以文本形式出现的符号引用,比如:
◆类和接口的全限定名;
◆字段的名称和描述符;
◆方法和名称和描述符。
如果是编译期已经创建好(直接用双引号定义的)的就存储在常量池中,如果是运行期(new出来的)才能确定的就存储在堆中。对于equals相等的字符串,在常量池中永远只有一份,在堆中有多份。
相关文章推荐
- Tomcat端口被占用解决方法(不用重启)
- “传奇”图象数据存储方式
- 超大数据量存储常用数据库分表分库算法总结
- SQL Server误区30日谈 第18天 有关FileStream的存储,垃圾回收以及其它
- C++实现图的邻接表存储和广度优先遍历实例分析
- C#调用sql2000存储过程方法小结
- PHP 存储文本换行实现方法
- 注册表中存储数据库链接字符串的方法
- Mysql中存储UUID去除横线的方法
- 深入PHP变量存储的详解
- MySQL存储毫秒数据的方法
- Android App中各种数据保存方式的使用实例总结
- Android在不使用数据库的情况下存储数据的方法
- Android使用文件进行数据存储的方法
- MongoDB系列教程(八):GridFS存储详解
- web.py在SAE中的Session问题解决方法(使用mysql存储)
- 我对块存储,文件存储,对象存储的认识
- 大型网站架构改进历程:存储的瓶颈(3)
- 大型网站架构改进历程:存储的瓶颈(1)
- 大型网站架构改进历程:存储的瓶颈(2)