Java JVM 是否像对 String 一样重用自定义 类 的相同不可变实例?
Does Java JVM reuse identical immutable instances of custom classes like it does with String?
如果你在一百个地方重新创建字符串“codecodecode”,实际上它只会存在一次,因为JVM是这样优化的。
但是这个class:
final public class ImmutReuseTest {
final public int num;
final public SomeImmutableThing thing;
public ImmutReuseTest(final int num, final SomeImmutableThing thing) {
this.num = num;
this.thing = thing;
}
}
final public class SomeImmutableThing {
final public int nomm;
final public String text;
public SomeImmutableThing(final int nomm, final String text) {
this.nomm = nomm;
this.text = text;
}
}
如果我创建了数千个 ImmutReuseTest 实例,其中一些实例将具有 100% 相等 值,JVM 是否会像它一样优化那些相等的实例细绳? (“相等”的意思是:各个字段在实例之间是相等的,关于“SomeImmutableThing”类型的字段,这意味着:那些事物的字段在那些事物实例之间也是相等的。)
如果实例具有完全相同的相同值怎么办? (“相同”的意思是:SomeImmutableThing 实例是相同的,而不仅仅是相等。)
如果我们将 SomeImmutableThing 更改为使用被认为是不可变但具有内部可变值的 class 会怎样(就像 String 一样,但由于专门的 JVM 优化,String 是一个不好的例子)?例如。让我们使用一个具有 public 可变字段但“有效最终”的字段。或仅具有“有效最终”的私有可变字段的字段。
If I create thousands of instances of ImmutReuseTest, of which some will have 100% equal values, will the JVM optimize those equal ones like it does with String?
答案是否定的。将 class 写成不可变的不会影响 JVM 管理其实例的方式。 Java 的 value types 作为 Valhalla 项目的一部分,旨在解决该问题。 String
优化确实是一个特例。
What about if the instances have the exact identical values? ("Identical" meaning: The SomeImmutableThing instances are the same instead of just being equal.)
是的,在这种情况下,只有一个实例具有该身份。
不确定我是否理解你的最后一个问题,但它似乎与第一个问题没有什么不同。
执行环境必须保留 Java 编程语言的语义,即 of the new
operator:
The value of a class instance creation expression is a reference to the newly created object of the specified class. Every time the expression is evaluated, a fresh object is created.
这不取决于您的 class 的可变性,只要 Java 没有提供除 new
以外的其他方法来实例化您的 class,那么除非您自己实施,否则不会共享实例。
您将(或可能)以重用对象结束的已知情况不涉及 new
,例如
String s = "foo";
Integer i = 42;
Runnable r = () -> System.out.println("hello");
此外,对于有意未指定对象标识的类型,如 Value-based Classes,实例总是通过工厂方法获取,因此它们实际实例化的方式对应用程序不可见。
对于真正的值类型,因为计划在未来的 Java 版本中添加,我们需要为 creating/getting 实例或语言规范更改的新语法结构new
运算符。
只要 JVM 不改变程序逻辑,它仍然可以做任何它想做的优化,所以如果它能证明应用程序从不对某些对象执行身份敏感操作或者可以假装那些操作仍然具有相同的效果(例如 new Foo() == new Foo()
可以替换为 false
),它可以将相同的对象折叠成一个。这显然很难或几乎不可能证明。
目前,当整个生命周期在优化器的范围内时,可以为短期对象完成。然而,在那些情况下,JVM 将完全消除分配,而不是搜索相同的对象以重用。参见 HotSpot Wiki/Escape Analysis…
如果你在一百个地方重新创建字符串“codecodecode”,实际上它只会存在一次,因为JVM是这样优化的。
但是这个class:
final public class ImmutReuseTest {
final public int num;
final public SomeImmutableThing thing;
public ImmutReuseTest(final int num, final SomeImmutableThing thing) {
this.num = num;
this.thing = thing;
}
}
final public class SomeImmutableThing {
final public int nomm;
final public String text;
public SomeImmutableThing(final int nomm, final String text) {
this.nomm = nomm;
this.text = text;
}
}
如果我创建了数千个 ImmutReuseTest 实例,其中一些实例将具有 100% 相等 值,JVM 是否会像它一样优化那些相等的实例细绳? (“相等”的意思是:各个字段在实例之间是相等的,关于“SomeImmutableThing”类型的字段,这意味着:那些事物的字段在那些事物实例之间也是相等的。)
如果实例具有完全相同的相同值怎么办? (“相同”的意思是:SomeImmutableThing 实例是相同的,而不仅仅是相等。)
如果我们将 SomeImmutableThing 更改为使用被认为是不可变但具有内部可变值的 class 会怎样(就像 String 一样,但由于专门的 JVM 优化,String 是一个不好的例子)?例如。让我们使用一个具有 public 可变字段但“有效最终”的字段。或仅具有“有效最终”的私有可变字段的字段。
If I create thousands of instances of ImmutReuseTest, of which some will have 100% equal values, will the JVM optimize those equal ones like it does with String?
答案是否定的。将 class 写成不可变的不会影响 JVM 管理其实例的方式。 Java 的 value types 作为 Valhalla 项目的一部分,旨在解决该问题。 String
优化确实是一个特例。
What about if the instances have the exact identical values? ("Identical" meaning: The SomeImmutableThing instances are the same instead of just being equal.)
是的,在这种情况下,只有一个实例具有该身份。
不确定我是否理解你的最后一个问题,但它似乎与第一个问题没有什么不同。
执行环境必须保留 Java 编程语言的语义,即 of the new
operator:
The value of a class instance creation expression is a reference to the newly created object of the specified class. Every time the expression is evaluated, a fresh object is created.
这不取决于您的 class 的可变性,只要 Java 没有提供除 new
以外的其他方法来实例化您的 class,那么除非您自己实施,否则不会共享实例。
您将(或可能)以重用对象结束的已知情况不涉及 new
,例如
String s = "foo";
Integer i = 42;
Runnable r = () -> System.out.println("hello");
此外,对于有意未指定对象标识的类型,如 Value-based Classes,实例总是通过工厂方法获取,因此它们实际实例化的方式对应用程序不可见。
对于真正的值类型,因为计划在未来的 Java 版本中添加,我们需要为 creating/getting 实例或语言规范更改的新语法结构new
运算符。
只要 JVM 不改变程序逻辑,它仍然可以做任何它想做的优化,所以如果它能证明应用程序从不对某些对象执行身份敏感操作或者可以假装那些操作仍然具有相同的效果(例如 new Foo() == new Foo()
可以替换为 false
),它可以将相同的对象折叠成一个。这显然很难或几乎不可能证明。
目前,当整个生命周期在优化器的范围内时,可以为短期对象完成。然而,在那些情况下,JVM 将完全消除分配,而不是搜索相同的对象以重用。参见 HotSpot Wiki/Escape Analysis…