JVM只对基本类型部分的数值保存在常量池里面:
说明:
Question:
My question is about java interning and constant pools.
Java maintains a a constants pool for java.lang.String
, to use JVM memory cleverly, and to do so java.lang.String is made immutable. So why doesn't java maintain constant pools of other immutable types, such as Long, Integer, Char, Short ? Wouldn't that save memory too ?
I am aware of the fact that Integers are pooled for value range [-127, 127], though I do not understand the reason for choosing this range.
Here's a test code I wrote to test pooling of other immutable data types.
public class PoolTest { public static void main(String... args) { // Pooling of Integer [-127, 127] Integer x = 127, y = 127; System.out.println("Integer:" + (x == y)); // prints true x = 129; y = 129; System.out.println("Integer:" + (x == y)); // prints false // Apparent pooling of short [-127, 127] Short i = 127, j = 127; System.out.println("Short: " + (i == j)); // prints true i = 128; j = 128; System.out.println("Short: " + (i == j)); // prints false // No pooling of long values Long k = 10L, l = 10L; System.out.println("Long: " + (i == j)); // prints false k = 128L; l = 128L; System.out.println("Long: " + (i == j)); // prints false } }
Answer:
The purpose of a constant pool is to reduce the memory overhead required by keeping multiple copies of constants. In the case of String
s, the JVM is inherently required to keep some object around for each individually distinguishable constant, and the Java spec basically says that the JVM should deduplicate String
objects when class loading. The ability to manually place String
s in the pool via intern
is inexpensive and allows programmers to identify particular values (such as properties) that are going to be around for the life of the program and tell the JVM to put them out of the way of normal garbage collection.
Pooling numeric constants, on the other hand, doesn't make a lot of sense, for a few reasons:
- Most particular numbers aren't ever used in a given program's code.
- When numbers are used in code, embedding them in the code as immediate opcode values is less expensive in terms of memory than trying to pool them. Note that even the empty
String
carries around achar[]
, anint
for its length, and another for itshashCode
. For a number, by contrast, a maximum of eight immediate bytes is required. - As of recent Java versions,
Byte
,Short
, andInteger
objects from -128 to 127 (0 to 127 forCharacter
) are precached for performance reasons, not to save memory. This range was presumably chosen because this is the ranged of a signed byte, and it will cover a large number of common uses, while it would be impractical to try to precache a very large number of values.
As a note, keep in mind that the rules about interning were made long before the introduction of autoboxing and generic types in Java 5, which significantly expanded how much the wrapper classes were casually used. This increase in use led Sun to add those common values to a constant pool.
相关推荐
在Java中,内存主要分为四个区域:寄存器、栈、堆和方法区(包括常量池)。以下是这四个区域的详细说明: 1. **寄存器**: 这是计算机硬件的一部分,用于存储非常快速访问的数据。在Java中,寄存器主要由JVM直接管理...
在Java内存管理中,堆(Heap)、栈(Stack)、常量池(Constant Pool)和方法区(Method Area)是四个核心概念,它们在Java程序运行时扮演着不同的角色。 首先,方法区是用来存放类的信息、常量、静态变量等数据的...
- 字符串常量和基本类型的常量通常存储在常量池中。 - 在常量池中,对于字符串而言,如果两个字符串相等(通过`equals`方法比较),则在常量池中只保留一份拷贝。 #### 非RAM存储 非RAM存储指的是那些持久化的...
### Java堆、栈和常量池详解 #### Java内存模型概览 在深入探讨Java中的堆、栈以及常量池之前,我们先来简要回顾一下Java内存模型的基本概念。Java程序运行时会使用到不同的内存区域来存储各种类型的数据,这些...
Java编程语言的基础知识中,数据类型和运行时常量池(Runtime Constant Pool)是两个关键概念。数据类型决定了变量可以存储的值的种类和大小,而运行时常量池则是Java虚拟机(JVM)内存模型中的一个重要组成部分。 ...
- **存储内容**:常量池包含代码中定义的各种基本类型和对象型的常量值,还包括以文本形式出现的符号引用,例如类和接口的全限定名、字段的名称和描述符、方法的名称和描述符等。 - **存储位置**:常量池存储在...
与此相似,整型常量池也独立出来,用于存储基本类型整数的常量。 整体来看,JDK8的JVM内存结构变化主要是为了优化内存管理和垃圾回收,减少溢出问题,同时提升性能。元空间的引入解决了永久代的一些固有问题,而...
常量池存储字符串常量和基本类型的常量(用public static final修饰)。在Java 8之前,字符串常量池位于方法区,从Java 8开始,字符串常量池被移到了堆中。常量池允许字符串的复用,减少了内存的消耗。例如,多个...
常量池是Java内存模型中的一个重要组成部分,它存储字符串常量和基本类型的final常量。在编译阶段,所有的字符串文字会被放入常量池,以实现对象的共享,从而节省内存和提高运行效率。比较字符串时,使用`==`会检查...
在Java程序的编译过程中,每个`.class`文件都会包含一个常量池,这个常量池被称为Class常量池或者静态常量池。它存在于每个`.class`文件的`Constant Pool`部分,并在类加载时被创建。Class常量池主要存储两种类型的...
Java中的八种基本类型包装类(Byte、Boolean、Short、Character、Integer、Long、Float、Double)中,除了Boolean,其他七种为-128到127之间的整数值提供了常量池。这意味着,当你创建这些值的包装对象时,如果值在...
5. **常量池**:存放常量,包括但不限于字符串常量、基本类型常量以及对其他类型、字段和方法的符号引用。常量池在编译期确定,保存在`.class`文件中。 6. **非RAM存储**:如硬盘等永久存储空间,用于存储持久化...
常量池则存放字符串常量和基本类型常量,例如通过`public static final`定义的常量。字符串常量池在JVM启动时就已经初始化,并且在编译时期,如果字符串是在源码中直接定义的(例如`"China"`),它们会被放入常量池...
- 存储局部变量(如基本类型的变量和对象的引用)。 - 每个线程拥有一个独立的栈。 - 栈内存中的数据在方法执行完毕后会自动释放,因此栈内存的生命周期与方法的执行周期一致。 2. **堆(Heap)**: - 是Java...
Java字符池,也被称为常量池,是Java内存管理中一个关键的概念,主要用来存储编译期就已经确定的各种常量,包括字符串常量、类、方法、接口等信息。理解字符池对于优化Java程序性能至关重要。 1. **String对象与...
栈主要用于存储基本类型(如int、bool等)和引用类型(如对象实例)的引用。而堆则负责存储对象实例本身。然而,字符串并不直接在堆上分配,而是通过CLR的字符串常量池进行管理。 字符串常量池是一种优化机制,它的...
它包含字符串、基本类型常量、类和接口的全限定名、字段和方法的名称及描述符。常量池在方法区中,不是堆的一部分。 6. **非RAM存储**:这包括硬盘等持久化存储,通常用于文件系统、数据库等长期存储需求。 栈与堆...