Java JVM是否像使用String那样重用定制类的相同的不可变示例?

new9mtju  于 2022-11-07  发布在  Java
关注(0)|答案(2)|浏览(162)

如果您在一百个地方重新创建String“codecodecode”,实际上它只会存在一次,因为JVM是这样优化的。
但这门课怎么样:

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;
    }

}

1.如果我创建了数千个ImmutReuseTest示例,其中一些示例的值100%相等,JVM是否会像对String一样优化这些相等的示例?(“相等”的含义是:示例之间的各个字段是相等的,这对于类型为“SomeImmutableThing”的字段意味着:在这些事物示例之间,这些事物字段也是相等的。)
1.如果示例具有完全
相同的
值,情况会怎样?(“相同”的含义是:SomeImmutableThing示例是相同的,而不仅仅是相等。)
1.如果我们将SomeImmutableThing更改为使用一个被认为是不可变的类,但它具有内部可变值(就像String一样,但String是一个不好的例子,因为专门的JVM优化)呢?例如,让我们使用一个具有公共可变字段但“有效最终”的类。或者使用一个只有私有可变字段且“有效最终”的类。

0x6upsns

0x6upsns1#

执行环境必须保留Java编程语言的语义,即new运算符的语义:
类示例创建表达式的值是对指定类的新创建对象的引用。每次计算表达式时,都会创建一个新对象。
这并不取决于类的可变性,只要Java除了new之外没有提供其他方法来示例化类,就不会共享示例,除非你自己实现了它。
在已知的情况下,您将(或可能)以重用对象结束,而不涉及new,例如。

String s = "foo";
Integer i = 42;
Runnable r = () -> System.out.println("hello");

此外,对于有意未指定对象标识的类型(如Value-based Classes),始终通过工厂方法获取示例,因此应用程序无法看到示例的实际示例化方式。
对于真值类型,由于计划在未来的Java版本中添加,我们需要一个新的语法构造来创建/获取示例,或者需要一个关于new运算符的语言规范更改。
JVM仍然可以执行任何它想要的优化,只要它不改变程序逻辑,因此如果它可以证明应用程序从未对某些对象执行标识敏感的操作,或者可以假装这些操作仍然具有相同的效果(例如,new Foo() == new Foo()可以替换为false),它可以将相同的对象折叠成一个。这显然很难证明,甚至几乎不可能证明。
目前,当整个生命周期在优化器的范围内时,可以对生命周期较短的对象执行此操作。但是,在这些情况下,JVM将完全消除分配,而不是搜索相同的对象来重用。请参阅HotSpot Wiki/Escape Analysis...

wfveoks0

wfveoks02#

如果我创建了数千个ImmutReuseTest示例,其中一些示例的值100%相等,那么JVM是否会像对String那样优化这些相等的示例?
答案是否定的。编写一个不可变的类并不会影响JVM管理其示例的方式。Java的value types,作为Project Valhalla的一部分,旨在解决这个问题。String优化实际上是一个特例。
如果示例具有完全相同的值呢?(“相同”的意思是:SomeImmutableThing示例是相同的,而不仅仅是相等。)
是的,在本例中,只有一个示例具有该标识。
我不太明白你的最后一个问题,但它似乎和第一个问题没有什么不同。

相关问题