1.寄存器:最快的存储区, 由编译器根据需求进行分配,我们在程序中无法控制.
2. 栈:存放基本类型的变量数据和对象的引用,但对象本身不存放在栈中,而是存放在堆(new 出来的对象)或者常量池中(字符串常量对象存放在常量池中。)
3. 堆:存放所有new出来的对象。
4. 静态域:存放静态成员(static定义的)
5. 常量池:存放字符串常量和基本类型常量(public static final)。
6. 非RAM存储:硬盘等永久存储空间
这里我们主要关心栈,堆和常量池,对于栈和常量池中的对象可以共享,对于堆中的对象不可以共享。栈中的数据大小和生命周期是可以确定的,当没有引用指向数据时,这个数据就会消失。堆中的对象的由垃圾回收器负责回收,因此大小和生命周期不需要确定,具有很大的灵活性。
对于字符串:其对象的引用都是存储在栈中的,如果是编译期已经创建好(直接用双引号定义的)的就存储在常量池中,如果是运行期(new出来的)才能确定的就存储在堆中。对于equals相等的字符串,在常量池中永远只有一份,在堆中有多份。
如以下代码:
- String s1 = "china";
- String s2 = "china";
- String s3 = "china";
- String ss1 = new String("china");
- String ss2 = new String("china");
- String ss3 = new String("china");
- String s1 = "china";
- String s2 = "china";
- String s3 = "china";
- String ss1 = new String("china");
- String ss2 = new String("china");
- String ss3 = new String("china");
这里解释一下黄色这3个箭头,对于通过new产生一个字符串(假设为”china”)时,会先去常量池中查找是否已经有了”china”对象,如果没有则在常量池中创建一个此字符串对象,然后堆中再创建一个常量池中此”china”对象的拷贝对象。这也就是有道面试题:String s = new String(“xyz”);产生几个对象?一个或两个,如果常量池中原来没有”xyz”,就是两个。
对于基础类型的变量和常量:变量和引用存储在栈中,常量存储在常量池中。
如以下代码:
- int i1 = 9;
- int i2 = 9;
- int i3 = 9;
- public static final int INT1 = 9;
- public static final int INT2 = 9;
- public static final int INT3 = 9;
- int i1 = 9;
- int i2 = 9;
- int i3 = 9;
- public static final int INT1 = 9;
- public static final int INT2 = 9;
- public static final int INT3 = 9;
对于成员变量和局部变量:成员变量就是方法外部,类的内部定义的变量;局部变量就是方法或语句块内部定义的变量。局部变量必须初始化。
形式参数是局部变量,局部变量的数据存在于栈内存中。栈内存中的局部变量随着方法的消失而消失。
成员变量存储在堆中的对象里面,由垃圾回收器负责回收。
如以下代码:
- class BirthDate {
- private int day;
- private int month;
- private int year;
- public BirthDate(int d, int m, int y) {
- day = d;
- month = m;
- year = y;
- }
- 省略get,set方法………
- }
- public class Test{
- public static void main(String args[]){
- int date = 9;
- Test test = new Test();
- test.change(date);
- BirthDate d1= new BirthDate(7,7,1970);
- }
- public void change1(int i){
- i = 1234;
- }
- class BirthDate {
- private int day;
- private int month;
- private int year;
- public BirthDate(int d, int m, int y) {
- day = d;
- month = m;
- year = y;
- }
- 省略get,set方法………
- }
- public class Test{
- public static void main(String args[]){
- int date = 9;
- Test test = new Test();
- test.change(date);
- BirthDate d1= new BirthDate(7,7,1970);
- }
- public void change1(int i){
- i = 1234;
- }
}
对于以上这段代码,date为局部变量,i,d,m,y都是形参为局部变量,day,month,year为成员变量。下面分析一下代码执行时候的变化:
1. main方法开始执行:int date = 9;
date局部变量,基础类型,引用和值都存在栈中。
2. Test test = new Test();
test为对象引用,存在栈中,对象(new Test())存在堆中。
3. test.change(date);
i为局部变量,引用和值存在栈中。当方法change执行完成后,i就会从栈中消失。
4. BirthDate d1= new BirthDate(7,7,1970);
d1为对象引用,存在栈中,对象(new BirthDate())存在堆中,其中d,m,y为局部变量存储在栈中,且它们的类型为基础类型,因此它们的数据也存储在栈中。day,month,year为成员变量,它们存储在堆中(new BirthDate()里面)。当BirthDate构造方法执行完之后,d,m,y将从栈中消失。
5.main方法执行完之后,date变量,test,d1引用将从栈中消失,new Test(),new BirthDate()将等待垃圾回收。
转自:http://yde986.iteye.com/blog/809764
相关推荐
2. 在字符串常量池中查找是否存在值为"abc"的字符串,若不存在则创建一个新的`String`对象,并将字符串值"abc"放入常量池,若存在则直接返回该字符串的引用。 3. 将变量`str`指向这个`String`对象的引用。 这种方式...
在Java学习过程中,堆(Heap)和栈(Stack)是两个非常重要的概念,它们对于理解Java内存管理机制至关重要。很多初学者在接触到这两个概念时往往感到困惑,本文将深入浅出地介绍Java中的堆和栈,帮助大家更好地理解...
9. **字符串常量池**:Java 8中的字符串常量池位于堆中,而非方法区,提高了字符串操作的效率。 10. **并行与串行压缩老年代收集**:Java 8对老年代的垃圾收集进行了优化,提供了并行和串行两种压缩模式,以适应...
运行时常量池是方法区的一部分,存放编译期生成的各种字面量和符号引用,JDK8将运行时常量池存放于堆中。直接内存(堆外内存)用于存放不在JVM堆内的内存对象,由操作系统管理,通过DirectByteBuffer进行操作,避免...
字符串常量池是一个特殊的区域,位于Java虚拟机(JVM)的内存结构中的方法区或元空间。它存储了程序中所有的字符串字面量(即用双引号定义的字符串)。当一个字符串被创建时,JVM会首先检查池中是否存在相同的字符串...
3. **Java堆**:Java堆是JVM中最大的一块内存区域,用于存储对象实例和数组。堆被划分为新生代和老年代,新生代进一步细分为Eden区、Survivor区(S0和S1),用于对象的分配和垃圾回收策略,如复制算法。 4. **直接...
而在JDK 7及其后续版本中,HotSpot对方法区的实现进行了改进,将字符串常量池和静态变量等原本放置在永久代中的内容移到了Java堆中。因此,在新版本的HotSpot虚拟机中,类变量将会随着Class对象一起存放在Java堆中。...
- **运行时常量池**: 方法区的一部分,用于存放编译期生成的常量和符号引用。 #### 五、对象的内存布局与引用 - **直接指针访问**:对象的内存布局必须包含足够的信息以便直接访问到对象的数据。 - **引用类型**...
3. 方法区:运行时常量池,以及字符串常量池的处理。 4. 性能调优:JVM参数设置,内存溢出与栈溢出分析。 六、Java框架 1. Spring框架:IoC、AOP原理,Spring Boot与Spring Cloud的应用。 2. MyBatis:SQL映射,...
8. **内存管理**:JAVA中的内存分为栈、堆和方法区,栈存放方法和局部变量,堆存放对象,方法区存储代码片段、常量池和静态属性。基本数据类型变量直接存储值,引用数据类型变量存储对象的地址。 这些知识点构成了...
5. 运行时常量池:存储字符串常量和编译期计算得出的常量。 三、Java集合框架 1. List接口:有序且允许重复元素的集合,如ArrayList和LinkedList。 2. Set接口:不允许重复元素的集合,如HashSet和TreeSet。 3. Map...
运行时数据区是Java虚拟机(JVM)内存模型的核心组成部分,主要分为以下几个区域:程序计数器、虚拟机栈、本地方法栈、堆和方法区。本文将重点关注"堆"这一部分,它是Java应用程序中最大的内存区域。 堆是所有线程...
通过对《深入JAVA虚拟机》的学习,开发者可以更深入地了解JAVA程序的运行原理,提升程序性能,解决内存管理和多线程问题,以及更好地利用JVM提供的各种特性来优化代码。同时,这也是成为一名高级JAVA开发者的必备...
掌握栈和堆的区别,了解字符串常量池的作用,以及如何正确比较对象,是每个Java程序员必备的基础知识。通过深入学习这部分内容,开发者能够更好地控制程序的内存使用,提高程序的稳定性和性能。
这些区域包括寄存器、栈、堆、常量池、代码段和数据段。理解这些内存区域的工作原理对于深入学习Java编程至关重要。 1. **寄存器**:JVM内部的虚拟寄存器,用于快速存取数据,但程序无法直接控制。 2. **栈**:栈...
3. 字符串池:String对象在常量池中的存储。 4. 方法区的元空间:Java 8以后,方法区由元空间(Metaspace)替代,与物理内存直接关联。 六、最佳实践 1. 对象创建策略:避免大量小对象的创建,减少内存碎片。 2. ...
此外,还有方法区(在Java 8后被元空间取代),用于存放类的信息,如类的常量池、字段和方法数据等。了解这些内存区域的划分和交互,有助于理解内存泄漏和栈溢出等问题。 类加载机制是JVM的另一重要部分。JVM会根据...
3. **方法区(Method Area)**:这部分存储类信息,包括常量池、字段和方法数据。在Java 8之后,这部分被称为元空间(Metaspace)。 4. **本地方法栈(Native Method Stack)**:与C++的栈类似,但主要用于支持JNI...
方法区存储类的信息,如类的静态变量和常量池;本地方法栈则服务于Java的本地方法接口,如C/C++的调用;运行时数据区包含了程序计数器、虚拟机栈和本地方法栈等。 JVM的类加载机制遵循双亲委派模型,从Bootstrap ...
- **方法区**:存储类的信息(如常量池)、静态变量、即时编译后的代码等。 - **寄存器**:处理器的一部分,用于临时存储计算结果。 - **本地方法区**:用于存储Java虚拟机使用的本地方法。 ### 总结 通过以上内容...