java常量池(java常量池在方法区还是堆)

华为云服务器特价优惠火热进行中!

2核2G2兆仅需 38 元;4核4G3兆仅需 79 元。购买时间越长越优惠!更多配置及优惠价格请咨询客服。

合作流程:
1、点击链接注册/关联华为云账号:点击跳转
2、添加客服微信号:cloud7591,确定产品方案、价格方案、服务支持方案等;
3、客服协助购买,并拉微信技术服务群,享受一对一免费技术支持服务;
技术专家在金蝶、华为、腾讯原厂有多年工作经验,并已从事云计算服务8年,可对域名、备案、网站搭建、系统部署、AI人工智能、云资源规划等上云常见问题提供更专业靠谱的服务,对相应产品提供更优惠的报价和方案,欢迎咨询。

今天给各位分享java常量池的知识,其中也会对java常量池在方法区还是堆进行解释,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在开始吧!

微信号:cloud7591
如需了解更多,欢迎添加客服微信咨询。
复制微信号

本文目录一览:

Java中的几种常量池

字符串常量池:当类加载完成,在堆中生成字符串对象实例,然后将该字符串对象实例的引用值存到string pool中。

class文件常量池:用于存放编译器生成的各种字面量(Literal)和符号引用(Symbolic References)。

运行时常量池:当类加载到内存中后,jvm就会将class常量池中的内容存放到运行时常量池中。

Java运行时常量池是什么?

在class文件中,“常量池”是最复杂也最值得关注的内容。

Java是一种动态连接的语言,常量池的作用非常重要,常量池中除了包含代码中所定义的各种基本类型(如int、long等等)和对象型(如String及数组)的常量值还,还包含一些以文本形式出现的符号引用,比如:

类和接口的全限定名;

字段的名称和描述符;

方法和名称和描述符。

在C语言中,如果一个程序要调用其它库中的函数,在连接时,该函数在库中的位置(即相对于库文件开头的偏移量)会被写在程序中,在运行时,直接去这个地址调用函数;

而在Java语言中不是这样,一切都是动态的。编译时,如果发现对其它类方法的调用或者对其它类字段的引用的话,记录进class文件中的,只能是一个文本形式的符号引用,在连接过程中,虚拟机根据这个文本信息去查找对应的方法或字段。

所以,与Java语言中的所谓“常量”不同,class文件中的“常量”内容很非富,这些常量集中在class中的一个区域存放,一个紧接着一个,这里就称为“常量池”。

java中的常量池技术,是为了方便快捷地创建某些对象而出现的,当需要一个对象时,就可以从池中取一个出来(如果池中没有则创建一个),则在需要重复重复创建相等变量时节省了很多时间。常量池其实也就是一个内存空间,不同于使用new关键字创建的对象所在的堆空间。本文只从java使用者的角度来探讨java常量池技术,并不涉及常量池的原理及实现方法。个人认为,如果是真的专注java,就必须对这些细节方面有一定的了解。但知道它的原理和具体的实现方法则不是必须的。

常量池中对象和堆中的对象

[java] view plain copy

public class Test{

Integer i1=new Integer(1);

Integer i2=new Integer(1);

//i1,i2分别位于堆中不同的内存空间

System.out.println(i1==i2);//输出false

Integer i3=1;

Integer i4=1;

//i3,i4指向常量池中同一个内存空间

System.out.println(i3==i4);//输出true

//很显然,i1,i3位于不同的内存空间

System.out.println(i1==i3);//输出false

}

8种基本类型的包装类和对象池

java中基本类型的包装类的大部分都实现了常量池技术,这些类是Byte,Short,Integer,Long,Character,Boolean,另外两种浮点数类型的包装类则没有实现。另外Byte,Short,Integer,Long,Character这5种整型的包装类也只是在对应值小于等于127时才可使用对象池,也即对象不负责创建和管理大于127的这些类的对象。以下是一些对应的测试代码:

[java] view plain copy

public class Test{

public static void main(String[] args){

//5种整形的包装类Byte,Short,Integer,Long,Character的对象,

//在值小于127时可以使用常量池

Integer i1=127;

Integer i2=127;

System.out.println(i1==i2)//输出true

//值大于127时,不会从常量池中取对象

Integer i3=128;

Integer i4=128;

System.out.println(i3==i4)//输出false

//Boolean类也实现了常量池技术

Boolean bool1=true;

Boolean bool2=true;

System.out.println(bool1==bool2);//输出true

//浮点类型的包装类没有实现常量池技术

Double d1=1.0;

Double d2=1.0;

System.out.println(d1==d2)//输出false

}

}

String也实现了常量池技术

String类也是java中用得多的类,同样为了创建String对象的方便,也实现了常量池的技术,测试代码如下:

[java] view plain copy

public class Test{

public static void main(String[] args){

//s1,s2分别位于堆中不同空间

String s1=new String("hello");

String s2=new String("hello");

System.out.println(s1==s2)//输出false

//s3,s4位于池中同一空间

String s3="hello";

String s4="hello";

System.out.println(s3==s4);//输出true

}

}

最后

细节决定成败,写代码更是如此。

在JDK5.0之前是不允许直接将基本数据类型的数据直接赋值给其对应地包装类的,如:Integer i = 5;

但是在JDK5.0中支持这种写法,因为编译器会自动将上面的代码转换成如下代码:Integer i=Integer.valueOf(5);

这就是Java的装箱.JDK5.0也提供了自动拆箱. Integer i =5; int j = i;

Integer的封装:

[java] view plain copy

public static Integer valueOf(int i) {

final int offset = 128;

if (i = -128 i = 127) { // must cache

return IntegerCache.cache[i + offset];

}

return new Integer(i);

}

private static class IntegerCache {

private IntegerCache(){}

static final Integer cache[] = new Integer[-(-128) + 127 + 1];

static {

for(int i = 0; i cache.length; i++)

cache[i] = new Integer(i - 128);

}

}

由于cache[]在IntegerCache类中是静态数组,也就是只需要初始化一次,即static{......}部分,所以,如果Integer对象初始化时是-128~127的范围,就不需要再重新定义申请空间,都是同一个对象---在IntegerCache.cache中,这样可以在一定程度上提高效率。

JVM中常量池存放在哪里

java8之前:

java8之后:元数据区 Metaspace

由于 PermGen 内存管理的效果远没有达到预期,所以JCP已经着手去除PermGen的工作。在JDK7中,字符串常量已经从永久代移除。现今 JDK8 中 PermGen 已经被彻底移除,取而代之的是metaspace数据区,使用native内存,申请和释放由虚拟机负责管理。

那么,JVM中常量池到底存放在哪里?

Java6和6之前,常量池是存放在方法区(永久代)中的。

Java7,将常量池是存放到了堆中。

Java8之后,取消了整个永久代区域,取而代之的是元空间。 运行时常量池和静态常量池存放在元空间中,而字符串常量池依然存放在堆中。

Java程序运行时,没有赋值的基本类型变量会在内存中分配空间吗?

基本类型的变量如果是临时变量,只要定义了,就会分配内存空间,不管是否被赋值;如果是作为对象的属性出现,只要该对象不实例化,就不会分配内存空间。\x0d\x0a\x0d\x0a一个完整的Java程序运行过程会涉及以下内存区域:\x0d\x0a1、寄存器:JVM内部虚拟寄存器,存取速度非常快,程序不可控制。\x0d\x0a2、 栈:保存局部变量的值,包括:\x0d\x0a 1)用来保存基本数据类型的值;\x0d\x0a 2)保存类的实例,即堆区对象的引用(指针)\x0d\x0a 3)也可以用来保存加载方法时的帧\x0d\x0a3、堆:用来存放动态产生的数据,比如new出来的对象。注意创建出来的对象只包含属于各自的成员变量,并不包括成员方法。因为同一个类的对象拥有各自的成员变量,存储在各自的堆中,但是他们共享该类的方法,并不是每创建一个对象就把成员方法复制一次。\x0d\x0a\x0d\x0a4、常量池:JVM为每个已加载的类型维护一个常量池,常量池就是这个类型用到的常量的一个有序集合。包括直接常量(基本类型,String)和对其他类型、方法、字段的符号引用(1)。池中的数据和数组一样通过索引访问。由于常量池包含了一个类型所有的对其他类型、方法、字段的符号引用,所以常量池在Java的动态链接中起了核心作用。常量池存在于堆中。\x0d\x0a\x0d\x0a5、代码段:用来存放从硬盘上读取的源程序代码。\x0d\x0a6、数据段:用来存放static定义的静态成员。\x0d\x0a\x0d\x0a注意:\x0d\x0a 1.一个Java文件,只要有main入口方法,我们就认为这是一个Java程序,可以单独编译运行。\x0d\x0a 2.无论是普通类型的变量还是引用类型的变量(俗称实例),都可以作为局部变量,他们都可以出现在栈中。只不过普通类型的变量在栈中直接保存它所对应的值,而引用类型的变量保存的是一个指向堆区的指针,通过这个指针,就可以找到这个实例在堆区对应的对象。因此,普通类型变量只在栈区占用一块内存,而引用类型变量要在栈区和堆区各占一块内存。

java常量池的介绍就聊到这里吧,感谢你花时间阅读本站内容,更多关于java常量池在方法区还是堆、java常量池的信息别忘了在本站进行查找喔。

发布于 2023-02-28 05:02:30
收藏
分享
海报
56
目录

    忘记密码?

    图形验证码

    复制成功
    微信号: cloud7591
    如需了解更多,欢迎添加客服微信咨询。
    我知道了