JAVA: 堆,栈,常量池

堆、栈和字符串常量池:Java内存管理的核心解析 Java虚拟机(JVM)的内存模型是我们讨论的起点。在这一部分,我们将简要介绍JVM的内存结构,解释堆、栈和字符串常量池在其中的位置和职责。理解这些内存区域在Java程序执行中的角色是深入探讨其工作原理的基础。 阅读详情

本片博客主要是粗略的对JVM中堆、栈、方法区的内容做个总结,更详细的内容,在本人马上学习了JVM的知识后,给大家分享,同时也方便自己以后复习学习;

特别感谢一下几篇博文,本文很多地方都是在这些博文的基础上加上自己的理解而写的,所以特此鸣谢如下:
》》Java内存分配之堆、栈和常量池 - Sara早安 - 博客园
》》Java常量池理解与总结
》》触摸java常量池
》》JAVA常量池理解与总结


1. 栈、堆、常量池的介绍

1.1 栈:

  在函数中定义的一些基本类型的变量及变量所对应的数据 和 对象的引用变量(包括 在堆中由new创建的对象和在常量池中存在的基本类型的包装类和直接赋值的String类)都在栈内存中分配。
  当在一段代码块定义一个局部的基本类型变量时,Java就在栈中为这个变量分配内存空间,当该变量退出该作用域后,Java会自动释放掉为该变量所分配的内存空间,该内存空间可以立即被另作他用。

1.2 堆 :

  堆内存用来存放由 new 创建的对象; 数组;和 不满足常量池技术的基本类型的包装类的对象。在堆中产生了一个数组或对象后,还可以 在栈中定义一个特殊的变量(称其为引用变量),让栈中这个引用变量的取值等于数组或对象在堆内存中的首地址。引用变量就相当于是为数组或对象起的一个名称,以后就可以在程序中使用栈中的引用变量来访问堆中的数组或对象。在堆中分配的内存,由Java虚拟机的自动垃圾回收器来管理。

  引用变量是普通的变量,定义时在栈中分配,引用变量在程序运行到其作用域之外后被释放。而数组和对象本身在堆中分配,即使程序运行到使用 new 产生数组或者对象的语句所在的代码块之外,数组和对象本身占据的内存不会被释放,数组和对象在没有引用变量指向它的时候,才变为垃圾,不能在被使用,但仍 然占据内存空间不放,在随后的一个不确定的时间被垃圾回收器收走(释放掉)。这也是 Java 比较占内存的原因。 实际上,栈中的变量指向堆内存中的变量,这就是Java中的指针!

1.3 常量池 :

  常量池存在于JVM的方法区中,虚拟机必须为每个被装载的类型维护一个常量池。主要分为两种:一种是在加载class文件中的一些数据也就是编译期产生的常量,另一种是运行时产生的常量;
  Class文件中的常量池:指的是在编译期被确定,并被保存在已编译的.class文件中的一些字面量如文本字符串,声明为final的常量值等,还包含一些以文本形式出现的符号引用,比如:

  • 1.类和接口的全限定名;
  • 2.字段的名称和描述符;
  • 3.方法和名称和描述符。

      主要包含: 实现了常量池的、并由基本类型的包装类直接声明初始化的变量(例如 Integer i =120); 由String 直接初始化的变量 (例如String str =”abc”); 对于String常量,它的值是在常量池中的。而JVM中的常量池在内存当中是以表的形式存在的, 对于String类型,有一张固定长度的CONSTANT_String_info表用来存储文字字符串值,注意:该表只存储文字字符串值,不存储符号引 用。例如 String str =“abc”; 在常量池中开辟一个内存把字符串的值“abc”存在这个内存中,而他的符号引用 String str是存在栈中的,并且这个引用变量的值是“abc”在常量池中的地址。

堆与栈的比较:

  Java的堆是一个运行时数据区,类的(对象从中分配空间。这些对象通过new、newarray、 anewarray和multianewarray等指令建立,它们不需要程序代码来显式的释放。堆是由垃圾回收来负责的,堆的优势是可以动态地分配内存大小,生存期也不必事先告诉编译器,因为它是在运行时动态分配内存的,Java的垃圾收集器会自动收走这些不再使用的数据。但缺点是,由于要在运行时动态 分配内存,存取速度较慢。

  栈的优势是,存取速度比堆要快,仅次于寄存器,栈数据可以共享。但缺点是,存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。栈中主要存放一些基本类型的变量数据(int, short, long, byte, float, double, boolean, char)和对象句柄(引用)。

数据共享:

  对于栈和常量池中的对象可以共享,对于堆中的对象不可以共享。


以字符串和基本类型及其包装类来详细分析这些问题:

2. 字符串的内存分配:

对于字符串,其对象的引用都是存储在栈中的,如果是编译期已经创建好(直接用双引号定义的,例如String str =”aaa” )的字符串的值也就是”aaa” 就存储在常量池中,如果是运行期(new出来的)才能确定的就存储在堆中。对于equals相等的字符串,在常量池中永远只有一份,在堆中有多份。注意String类重写了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");

System.out.println("s1==s2  :" + (s1==s2));// true
System.out.println("s1==s3  :" + (s1==s3));// true
System.out.println("s2==s3  :" + (s2==s3));// true
System.out.println("ss1==ss2  :" + (ss1==ss2));//false
System.out.println("ss1==ss3  :" + (ss1==ss3));//false
System.out.println("ss2==ss3  :" + (ss2==ss3));//false

这里写图片描述

细节分析:
对于String s1="china"; String s2="china"; String s3="china";创建过程解析:
首先当JVM都到String s1="china" 时,会在 栈 中定义一个 名字为 s1 的对String类型的 引用变量 String str;然后 会去常量池中查找是否有值为“china”的一块内存存在,如果没有找到,则开辟一块内存,并且字符串的值“abc”存入,然后将这块内存地址赋给栈中的引用变量,也就是引用变量s1的值常量池中“china”的内存地址;如果找到了,则直接将这块内存地址的值赋给栈中的引用变量;接下来,当JVM读到String s2="china" 时,通用会在栈中定义一个引用变量s2, 然后去常量池中查找,此时发现有“china”的内存块存在,则直接将这个内存块的地址返给栈中的引用变量 s2;接下来相应的有s2;所以他们三个存放的是同一块地址;

这里解释一下黄色这3个箭头,当JVM读取到String ss1 = new String("china") 也就是对于通过new产生一个字符串时,JVM会 在 栈 中定义一个名字为 ss1 的对String类型的 对象引用变量 String ss1 ; 然后会去常量池中查找是否已经有了“china”对象,如果没有则在常量池中创建一个此字符串对象,如果存在,然后在堆中再创建一个常量池中此”china”对象的拷贝对象。

  思考:String str = new String("xyz") ; 产生几个对象?一个或两个,如果常量池中原来没有”xyz”,就是两个。

  思考: String 的 public native String intern() ; 方法,
  存在于.class文件中的常量池,在运行期被JVM装载,并且可以扩充。String 的 intern() 方法就是扩充常量池的 一个方法;当一个 String实例 str 调用 intern() 方法时,JVM 查找常量池中是否有相同Unicode的字符串常量;如果有,则返回其引用;如果没有,则在常量池中增加一个Unicode等于str的字符串并返回它的引用。
  

String s0= "kvill";   
String s1=new String("kvill");   
String s2=new String("kvill");   
System.out.println( s0==s1 );   // false  
s1.intern();   
//虽然存在但是没有接受返回的目标,此时s1还是指向堆中的对象
s2=s2.intern(); 
//存在,所以把常量池中"kvill"的引用赋给s2,此时s2存的不是堆对象的地址而是常量池中字符对象的地址; 
System.out.println( s0==s1); //false   
System.out.println( s0==s1.intern() ); //true   
System.out.println( s0==s2 ); //true;
2.2 字符串 拼接符合 “+”引起的几个问题

以下的内容有的是自己推理出来的,因为还没有仔细研究反编译的东西,而且网上找到几篇博文,对这方面说的也不是特别清楚,如果问题,请看到的朋友多多指点,
jdk7会自动处理将 + 号链接字符串的情况:

"hello: "+msg

反编译:

(new StringBuilder()).append("hello : ").append(msg).toString()

也就是说 JVM 在对于编译期没法确定的其值到底是什么的字符串,在运行前会通过new StringBuilder()的方式进行连接处理;那么自然这个字符串对象是存在堆内存中;

【1】
String a = "ab";   
String x = "b";   
String b = "a" + x;   
System.out.println((a == b)); //false 

【1】中,JVM对于字符串引用,由于在字符串的”+”连接中,有字符串引用存在,而引用的值在程序编译期是无法确定的,即”a” + bb无法被编译器优化,只有在程序运行期来动态分配并将连接后的新地址赋给b。而在运行期就会借住new StringBuilder() 来处理,自然会将结果放在堆内存中,所以上面程序的结果也就为false。

【2】
String a = "ab";   
final String x = "b";   
String b = "a" + bb;   
System.out.println((a == b)); //result = true 

【2】对于final修饰的变量,它在编译时被解析为常量值的一个本地拷贝存储到自己的常量池中或嵌入到它的字节码流中。所以此时的”a” + bb和”a” + “b”效果是一样的。故上面程序的结果为true。

【3】
String a = "ab";   
final String bb = getBB();   
String b = "a" + bb;   
System.out.println((a == b)); //result = false   
private static String getBB() {  
return "b";   
}

【3】JVM对于字符串引用bb,它的值在编译期无法确定,只有在程序运行期调用方法后,将方法的返回值和”a”来动态连接并分配地址为b,故上面程序的结果为false。

String s1 = "str";
String s2 = "ing";

String s3 = "str" + "ing";
String s4 = s1 + s2;
System.out.println(str3 == str4);//false

String s5 = "string";
System.out.println(s3 == s5);//true
public static final String A;    // 常量A
public static final String B;    // 常量B
static {   
    A = "ab";   
    B = "cd";   
}   
public static void main(String[] args) {   
    // 将两个常量用+连接对s进行初始化   
    String s = A + B;   
    String t = "abcd"; 
    System.out.println(s==t) //false
}  

3. 基本变量类型及其包装类的问题分析

对于基础类型的变量和常量,变量和引用存储在栈中,常量存储在常量池中。

int i1 = 9;
int i2 = 9;
int i3 = 9;

final int INT1 = 9;
final int INT2 = 9;
final int INT3 = 9;

这里写图片描述

主要栈和常量池中的数值是可以共享的,对int i1=9; int i2=9; int i3 =9; 的详细分析:
JVM读到 int i1=9 首先它会在栈中创建一个变量为i1的引用,然后查找栈中是否有9这个值,如果没找到,就开辟一块内存并且将9存放进来,然后将 i1 指向 9 也就是将这块内存的地址赋给 i1。接着处理 int i2 = 9; 在创建完i2的引用变量后,因为在栈中已经有9这个值,便将i2直接指向9。这样,就出现了i1与i2同时均指向9的情况。最后i3也指向这个9。

3.2 基本类型的包装类在内存中的分配

Java的8种基本类型包装器(Byte, Short, Integer, Long, Character, Boolean, Float, Double), 除 Float 和 Double 以外, 其它六种都实现了常量池, 是它们只在 [-128, 127] 才使用常量池。而如果大于127 或小于-128 则不会使用常量池所以会直接在堆内存中创建对象。

Integer i1 = 127;
Integer i2 = 127;
System.out.println(i1==i2);//true 栈存引用变量,常量池存值

Integer i3 = 128;
Integer i4 = 128;
System.out.println(i3==i4);//false 栈存引用变量,堆中存值;

int i5 = 234;
int i6 = 234;
System.out.println("i5==i6 "+(i5==i6));//true 都存在栈中;

int i71 = 343;
Integer i72=343;
Integer i8 = new Integer(343);
System.out.println(i71==i72);//true 不知道为什么,只要是值相等就是true
System.out.println("why "+(i71==i8));//true
System.out.println("why : "+(i72==i8));//false 

Integer ii1 = 40;
Integer ii2 = 40;
Integer ii3 = 0;
Integer ii4 = new Integer(40);
Integer ii5 = new Integer(40);
Integer ii6 = new Integer(0);

System.out.println("ii1=ii2   " + (ii1 == ii2));//true
System.out.println("ii1=ii2+ii3   " + (ii1 == ii2 + ii3));//true
System.out.println("ii1=ii4   " + (ii1 == ii4));//false
System.out.println("ii4=ii5   " + (ii4 == ii5));//false
System.out.println("ii4=ii5+ii6   " + (ii4 == ii5 + ii6));//true   
System.out.println("40=ii5+ii6   " + (40 == ii5 + ii6));//true

Integer ii7 = 200;
Integer ii8 = 200;
int ii =0;
System.out.println(ii7==i8+ii);//true
Integer ii9 = new Integer(400);
Integer ii10 = new Integer(400);
Integer ii11 = new Integer(0);
System.out.println(ii9 == ii10+ii);//true

因为+这个操作符不适用于Integer对象,所以都进行自动拆箱操作,进行数值相加,即 ii10+ii = 400。然后Integer对象无法与数值进行直接比较,所以ii9自动拆箱转为int值400,最终这条语句转为400 == 400进行数值比较。

4. 成员变量和局部变量在内存中的分配

  对于成员变量和局部变量:成员变量就是方法外部,类的内部定义的变量;局部变量就是方法或语句块内部定义的变量。局部变量必须初始化。 形式参数是局部变量,
  局部变量的数据存在于栈内存中。栈内存中的局部变量随着方法的消失而消失。 成员变量存储在堆中的对象里面,由垃圾回收器负责回收。 如以下代码:

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 change(int i) {
        i = 1234;
    }
}

这里写图片描述

对于以上这段代码,date为局部变量,i, d, m, y都是形参为局部变量,day,month,year为成员变量。下面分析一下代码执行时候的变化:

  • main方法开始执行:int date = 9; date 为局部变量,基础类型,引用和值都存在栈中。
  • Test test = new Test(); test 为对象引用,存在栈中,对象 (new Test())存在堆中。
  • test.change(date); i 为局部变量,引用和值存在栈中。当方法change 执行完成后,i 就会从栈中消失。
  • BirthDate d1= new BirthDate(7,7,1970);d1 为对象引用,存在栈中,对象(new BirthDate())存在堆中,其中d,m,y为局部变量存储在栈中,且它们的类型为基础类型,因此它们的数据也存储在栈中。day,month,year为成员变量,它们存储在堆中(new BirthDate()里面)。当BirthDate构造方法执行完之后,d,m,y将从栈中消失。
  • main方法执行完之后,date变量,test,d1引用将从栈中消失,new Test(), new BirthDate()将等待垃圾回收。
内存分配及变量存储位置(堆、栈、方法区常量池、方法区静态区)(转) 程序运行时,有六个地方都可以保存数据:   1、 寄存器:这是最快的保存区域,因为它位于和其他所有保存方式不同的地方:处理器内部。然而,寄存器的数量十分有限,所以寄存器是根据需要由编译器分配。我们对此没有直接的控制权,也不可能在自己的程序里找到寄存器存在的任何踪迹。   2、 堆栈:存放基本类型的数据和对象的引用,但对象本身不存放在栈中,而是存放在堆中(new 出来的对象)。驻留于常规RAM(随机访问存储器)区域。但可通过它的“堆栈指针”获得处理的直接支持。堆栈指针若向下移,会创建新的内存;若向上移,则会 阅读详情

相关推荐

Java实战:用Proj4j搞定WGS84与CGCS2000坐标互转(附完整代码)

本文详细介绍了如何使用Java库Proj4j实现WGS84与CGCS2000坐标系之间的高精度转换。通过七参数转换模型和格网改正量文件,提供完整的代码实现和项目配置指南,帮助开发者快速集成到地理信息系统项目中,提升坐标转换效率和精度。

weixin_29251567的博客 827

Java 类和对象在内存中的表现形式,栈、堆、方法区、常量池

java

m0_56863607的博客 1703

VS2017中调用gdal(C#版)的方法二(含gdal下载地址,配置过程,代码测试,超详细!!)

VS2017中gdal(C#)版的配置与测试 上次记录了直接在VS2017中下载并应用gdal的方法,这次来记录一下网上下载的安装包配置与测试的方法。 一、环境、版本及下载地址 win10,vs2017社区版,gdal2.4.4 还是像之前在Unity中应用gdal一样,最好是下载已经编译好的C#版的gdal,不然自己配置真的很容易出错,我就是这样的,下面提供不同版本的gdal下载地址: 1.GDAL2.4.4(C#版、64位): https://download.youkuaiyun.com/download/che

chengbaola的博客 1365

举例讲解JAVA中的堆和栈

Java中堆和堆栈的区别     1. 栈(stack)与堆(heap)都是Java用来在Ram中存放数据的地方。与C++不同,Java自动管理栈和堆,程序员不能直接地设置栈或堆。 (降低内存或者说是程序方面的内存泄露等问题出现的几率?) 2. 栈的优势是,存取速度比堆要快,仅次于直接位于CPU中的寄存器。但缺点是,存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。另外,

Java海洋 2476

基于R语言的DICE模型实践技术应用;预测不同减排路径下的经济增长、碳排放量、气候变化程度以及社会福利变化

DICE模型是一个动态综合气候经济模型,由诺贝尔经济学奖得主William Nordhaus开发,用于评估气候变化对经济的影响以及不同减排政策的经济成本和效益。以下是一个关于DICE模型在气候变化影响评估中的实际应用案例,结合R语言代码进行讲解。

KY_chenzhao的博客 866

模电实验室:手把手教你调试共射放大电路静态工作点(避免波形失真)

本文详细介绍了共射放大电路静态工作点的调试方法,帮助避免波形失真问题。从实验准备、电路搭建到静态工作点测量,提供了实用的电阻选值策略和常见波形失真解决方案,适合电子相关专业学生和硬件工程师参考学习。

weixin_42531128的博客 375

Java堆、栈、方法区、常量池

Java堆、栈、方法区、常量池

qq_48287999的博客 2770

电子凸轮追剪算法深度解析:2500字图解+代码实战

工艺需求:在物料连续运动过程中完成精准切割核心矛盾:切割瞬间刀具与物料必须绝对同步传统方案:机械凸轮(结构复杂,调整困难)现代方案:电子凸轮(柔性可调,精度更高)

QQ_778132974的博客 1106

堆、栈、常量池的理解

本文对java的栈、堆和常量池之间的关系以及存放的内容讲一些个人浅显的理解

qurious7的博客 890

领域知识图谱构建的技术流程

因此概念的属性定义十分重要,通常大部分知识库中的概念属性都是采用人工定义等方式生成的,通用知识图谱则可以从开放数据集中获取概念的属性,然后从在线百科中学习实体的属性,并对实体属性进行往上规约从而生成概念的属性。由于百科的分类体系都是经过了百科管理员或是高级编辑人员的校验,其分类系统中的数据可靠性非常高,因此从百科中抽取概念和实体,通常将标题作为实体的候选,而将百科中的分类系统直接作为概念的候选。为了对知识进行合理的组织,更好地描述知识本身与知识之间的关联,需要对知识图谱的模式进行良好的定义。

weixin_43961909的博客 333

YOLOv8改进 | Conv篇 | 利用YOLOv9的GELAN模块替换C2f结构(附轻量化版本 + 高效涨点版本 + 结构图)

本文给大家带来的改进机制是利用2024/02/21号最新发布的YOLOv9其中提出的GELAN模块来改进YOLOv8中的C2f,GELAN融合了CSPNet和ELAN机制同时其中利用到了RepConv在获取更多有效特征的同时在推理时专用单分支结构从而不影响推理速度,同时本文的内容提供了两种版本一种是参数量更低涨点效果略微弱一些的版本(参数量V8n下降80w,计算量为6.1GFLOPs),另一种是参数量稍多一些但是效果要不参数量低的效果要好一些(均为我个人整理),提供两种版本是为了适配不同需求的读者,具体选择

Snu77的博客 7564

Java 堆、栈、常量池

<br />     1.寄存器:最快的存储区, 由编译器根据需求进行分配,我们在程序中无法控制.<br /><br />2. 栈:存放基本类型的变量数据和对象的引用,但对象本身不存放在栈中,而是存放在堆(new 出来的对象)或者常量池中(字符串常量对象存放在常量池中。)<br /><br />3. 堆:存放所有new出来的对象。<br /><br />  4. 静态域:存放静态成员(static定义的)<br /><br />5. 常量池:存放字符串常量和基本类型常量(public static fina

张国鹏的专栏 883

搞懂 SAPUI5 Fiori 应用的 OData 授权维护:从 IWSG、IWSV 到 S_SERVICE 的完整实践

本文探讨了SAP Fiori项目中常见的授权问题及其解决方案。文章指出,开发人员常误将OData服务访问问题归咎于前端代码或配置,而实际上多因授权默认值未正确带入角色所致。详细分析了IWSG(前端服务组元数据)和IWSV(后端业务服务)两个关键对象的作用机制,强调应通过PFCG角色的Authorization Default入口维护服务对象,而非直接修改S_SERVICE授权对象。文章还提供了前后端授权配置的具体操作步骤,并特别提醒需同时配置前端和后端授权,才能确保应用完整可用性。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 205

java 内存分析 栈 堆 常量池_深入解析:Java内存分配之堆、栈和常量池

Java内存分配主要包括以下几个区域1. 寄存器:我们在程序中无法控制2. 栈:存放基本类型的数据和对象的引用,但对象本身不存放在栈中,而是存放在堆中3. 堆:存放用new产生的数据4. 静态域:存放在对象中用static定义的静态成员5. 常量池:存放常量6. 非RAM(随机存取存储器)存储:硬盘等永久存储空间Java内存分配中的栈在函数中定义的一些基本类型的变量数据和对象的引用变量都在函数的栈...

weixin_29522501的博客 163

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

主题:Java堆.栈和常量池 笔记

今天复习了一下这些知识,顺便做了下笔记. 1.寄存器:最快的存储区, 由编译器根据需求进行分配,我们在程序中无法控制. 2. 栈:存放基本类型的变量数据和对象的引用,但对象本身不存放在栈中,而是存放在堆(new 出来的对象)或者常量池中(字符串常量对象存放在常量池中。) 3. 堆:存放所有new出来的对象。 4. 静态域:存放静态成员(static定义的) 5. 常量池:存放字符串常量和...

iteye_10679的博客 187

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

java 常量池 方法区_Java栈、Java堆、方法区和常量池:

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。本文链接:https://blog.youkuaiyun.com/qq_34490018/article/details/82110578目录JVM相关知识String源码分析Srtring在JVM层解析String典型案例String被设计成不可变和不能被继承的原因JVM相关知识下面这张图是JVM的体系结...

weixin_33745006的博客 319

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

stringbuilder调用tostring常量池_深入解析:Java内存分配之堆、栈和常量池

Java内存分配主要包括以下几个区域:1. 寄存器:我们在程序中无法控制2. 栈:存放基本类型的数据和对象的引用,但对象本身不存放在栈中,而是存放在堆中3. 堆:存放用new产生的数据4. 静态域:存放在对象中用static定义的静态成员5. 常量池:存放常量6. 非RAM(随机存取存储器)存储:硬盘等永久存储空间******************************************...

weixin_39845039的博客 962

释放变量所指向的内存_深入解析:Java内存分配之堆、栈和常量池

Java内存分配主要包括以下几个区域:1. 寄存器:我们在程序中无法控制2. 栈:存放基本类型的数据和对象的引用,但对象本身不存放在栈中,而是存放在堆中3. 堆:存放用new产生的数据4. 静态域:存放在对象中用static定义的静态成员5. 常量池:存放常量6. 非RAM(随机存取存储器)存储:硬盘等永久存储空间******************************************...

weixin_39785600的博客 218

Java内存分配:Java堆.栈和常量池

Java堆.栈和常量池 博客分类: Java JavaJVM虚拟机嵌入式  Java内存分配: 1. 寄存器:我们在程序中无法控制2. 栈:存放基本类型的数据和对象的引用,但对象本身不存放在栈中,而是存放在堆中3. 堆:存放用new产生的数据4. 静态域:存放在对象中用static定义的静态成员5. 常量池:存放常量6. 非RAM存储:硬盘等永久存储空间-------...

xkhzk2的博客 130

Java学习笔记52:Java堆、栈和常量池

1.寄存器:最快的存储区, 由编译器根据需求进行分配,我们在程序中无法控制. 2. 栈:存放基本类型的变量数据和对象的引用,但对象本身不存放在栈中,而是存放在堆(new 出来的对象)或者常量池中(字符串常量对象存放在常量池中。) 3. 堆:存放所有new出来的对象。 4. 静态域:存放静态成员(static定义的) 5. 常量池:存放字符串常量和基本类型常量(publi

自娱自乐的代码人 1217

Java 的栈、堆和常量池以及创建对象&赋值

本博客仅作为学习笔记,参考自: 1.Java中的栈,堆,方法区和常量池_听雨居-优快云博客要说Java中的栈,堆,方法区和常量池就要提到HotSpot,HotSpot是Sun JDK 和 Open JDK中所带的虚拟机。(Sun JDK 和 Open JDK除了注释不同,代码实现基本上是一样的)Stack(栈):分为VM Stack(虚拟机栈)和Native Method Stack(本地方法栈),不过HotSpot虚拟机直接把本地方法栈和虚拟机栈合二为一了。虚拟机栈: 线程私...https:...

qq_42324085的博客 1405

java中的堆、栈、常量池 分类: java 201...

Java内存分配: 1. 寄存器:我们在程序中无法控制2. 栈:存放基本类型的数据和对象的引用,但对象本身不存放在栈中,而是存放在堆中3. 堆:存放用new产生的数据4. 静态域:存放在对象中用static定义的静态成员5. 常量池:存放常量6. 非RAM(随机存取存储器)存储:硬盘等永久存储空间------------------------------------------------...

weixin_30399055的博客 87

Java内存区域:堆、栈、方法区、运行时常量池、直接内存

Java内存区域 目录 文章目录Java内存区域目录介绍运行时数据区域程序计数器(线程私有)Java虚拟机栈(线程私有)本地方法栈(线程私有)堆方法区运行时常量池直接内存 介绍 Java虚拟机在执行Java程序的过程中将自己所管理的内存区域划分为不同的数据区域。有的区域随着虚拟机进程的启动而一直存在,有的则是跟随线程的启动和结束而建立和销毁。 运行时数据区域 Java虚拟机运行时数据区结构: 程序计数器(线程私有) 当前线程所执行的字节码行号指示器,所占内存很小,如果在执行的是一个Java方法,那么他的值

qq_41868309的博客 625

java堆和栈 常量池_GitHub - han-guang-xue/difference-of-stack-heap-pool: Java中堆、栈和常量池的区别...

Java中堆、栈和常量池的区别栈 堆 常量池的概念首先我们先了解一下概念,Java把内存分成两种,一种叫做栈内存,一种叫做堆内存。栈内存存放基本类型的变量数据和对象类型的引用(请注意存放的是引用),对象本身不存放在栈中,而是存放在堆(new 出来的对象)或者常量池中(字符串常量对象存放在常量池中)堆内存堆内存用来存放由new创建的对象和数组。在堆中分配的内存,由java虚拟机自动垃圾回收器来管理常...

weixin_33701632的博客 133

Java堆、栈和常量池-longxiaoyan

d1为对象引用,存在栈中,对象(new BirthDate())存在堆中,其中d,m,y为局部变量存储在栈中,且它们的类型为基础类型,因此它们的数据也存储在栈中。对于字符串:其对象的引用都是存储在栈中的,如果是编译期已经创建好(直接用双引号定义的)的就存储在常量池中,如果是运行期(new出来的)才能确定的就存储在堆中。2. 栈:存放基本类型的变量数据和对象的引用,但对象本身不存放在栈中,而是存放在堆(new 出来的对象)或者常量池中(字符串常量对象存放在常量池中。栈内存中的局部变量随着方法的消失而消失。

PP 364

java堆和栈 常量池_Java中栈、堆和常量池

Java内存分配主要包括以下几个区域:寄存器最快的存储区, 由编译器根据需求进行分配,我们在程序中无法控制.。栈存放基本类型的变量数据和对象的引用(就是一个名字),对象本身不存放在栈中,而是存放在堆或者常量池中。栈内存归属于单个线程,每个线程都会有一个栈内存,其存储的变量只能在其所属线程中可见,即栈内存可以理解成线程的私有内存。栈区内存由编译器自动分配释放,具体方法执行结束之后,系统自动释放JVM...

weixin_29973077的博客 1166
上一篇: JAVA: equals 思考
下一篇: Java异常机制与 finally 与return的关系;
Coder-Qian
博客等级 码龄11年 63粉丝 73原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值