String 新建字符串对象创建-在普通内存和字符串常量池中分配内存?二者都

String 新建字符串对象创建-在普通内存和字符串常量池中分配内存?二者都,string,memory-management,jvm,String,Memory Management,Jvm,当我们使用new关键字时,Java将在普通(非工具)内存中创建一个新的String对象,s将引用它。此外,文字“abc”将放置在池中 我在认证书上找到了这个信息。我对此很好奇,JVM在普通内存中添加了“abc”之后,又在字符串常量池中添加了“abc”,那么它为什么要在普通内存中创建“abc”?然而,它可以直接在字符串常量池中分配空间 这背后有一些原因?没有“正常内存”和“池内存”这样的东西 所有String实例都位于堆上,根据定义,堆是容纳所有Java对象的内存。有一个字符串池,它基本上是一种哈

当我们使用new关键字时,Java将在普通(非工具)内存中创建一个新的String对象,s将引用它。此外,文字“abc”将放置在池中

我在认证书上找到了这个信息。我对此很好奇,JVM在普通内存中添加了“abc”之后,又在字符串常量池中添加了“abc”,那么它为什么要在普通内存中创建“abc”?然而,它可以直接在字符串常量池中分配空间


这背后有一些原因?

没有“正常内存”和“池内存”这样的东西

所有
String
实例都位于堆上,根据定义,堆是容纳所有Java对象的内存。有一个字符串池,它基本上是一种哈希映射,包含对实例的引用。
String
实例不需要位于特殊的内存区域中,以供字符串池引用。向池中添加字符串并不意味着任何内存移动

在较旧的JVM中,为字符串文本创建的实例被放置在一个特殊的内存区域中,以降低被垃圾收集的可能性。由于称为永久生成的内存区域有一些缺点,所以放弃了该策略,并在Java8中删除了该内存区域。这种旧的行为可能会造成一些混乱。但池引用的字符串从来都不需要位于该内存区域中

除此之外,你的问题的目的还不清楚。您已经编写了请求Java创建两个不同的
String
实例的代码,Java将这样做。它这样做的原因是,因为你告诉过它

如果您真的想更深入地了解技术细节,那么您的代码将会发生什么:

  • 首先,为您的
    新字符串(…)
    请求创建一个未初始化的
    String
    实例
  • 然后,为
    “abc”
    文本创建一个
    字符串
    实例并将其添加到池中(除非池中已经包含该内容的字符串)
  • 最后,调用第一步创建的
    String
    实例的构造函数,第二步的
    String
    实例作为参数
    • 在构造函数中,将复制对
      char[]
      数组的引用

最后,根据您的请求,您有两个具有相同内容的实例,它们都指向相同的数组(自Java 7u6以来),因此单个数组显然不能位于两个字符串的不同内存区域。

没有“普通内存”和“池内存”这样的东西

所有
String
实例都位于堆上,根据定义,堆是容纳所有Java对象的内存。有一个字符串池,它基本上是一种哈希映射,包含对实例的引用。
String
实例不需要位于特殊的内存区域中,以供字符串池引用。向池中添加字符串并不意味着任何内存移动

在较旧的JVM中,为字符串文本创建的实例被放置在一个特殊的内存区域中,以降低被垃圾收集的可能性。由于称为永久生成的内存区域有一些缺点,所以放弃了该策略,并在Java8中删除了该内存区域。这种旧的行为可能会造成一些混乱。但池引用的字符串从来都不需要位于该内存区域中

除此之外,你的问题的目的还不清楚。您已经编写了请求Java创建两个不同的
String
实例的代码,Java将这样做。它这样做的原因是,因为你告诉过它

如果您真的想更深入地了解技术细节,那么您的代码将会发生什么:

  • 首先,为您的
    新字符串(…)
    请求创建一个未初始化的
    String
    实例
  • 然后,为
    “abc”
    文本创建一个
    字符串
    实例并将其添加到池中(除非池中已经包含该内容的字符串)
  • 最后,调用第一步创建的
    String
    实例的构造函数,第二步的
    String
    实例作为参数
    • 在构造函数中,将复制对
      char[]
      数组的引用
最后,根据您的请求,您有两个具有相同内容的实例,它们都指向相同的数组(自Java 7u6以来),因此单个数组显然不能位于两个字符串的不同内存区域中

String s = new String("abc");