Java 现代JVM是否优化只读集合分配

Java 现代JVM是否优化只读集合分配,java,optimization,jvm,Java,Optimization,Jvm,我有点好奇下面的优化可能性,但不知道如何验证自己,也许有人已经知道答案 我们的应用程序中有很多类似的代码。基本上,它是一个状态完整的处理程序(saga),由某条消息(MyStartingMessage)启动,随后可以由另一条消息(myctinuemessage)继续。因为这些StatefullHandler有多个实例,所以我们要检查Continue消息是否应该由给定实例处理。因此,我们在处理程序中设置了一些状态,当收到消息时,我们检查每个处理程序实例,如果消息中的状态与处理程序状态匹配,则只有该

我有点好奇下面的优化可能性,但不知道如何验证自己,也许有人已经知道答案

我们的应用程序中有很多类似的代码。基本上,它是一个状态完整的处理程序(saga),由某条消息(
MyStartingMessage
)启动,随后可以由另一条消息(
myctinuemessage
)继续。因为这些
StatefullHandler
有多个实例,所以我们要检查Continue消息是否应该由给定实例处理。因此,我们在处理程序中设置了一些状态,当收到消息时,我们检查每个处理程序实例,如果消息中的状态与处理程序状态匹配,则只有该消息由该处理程序实例处理

在下面所示的示例中,一些框架将提取匹配器,并检查这些匹配器是否与接收到的continue消息实例匹配

因为我们每秒处理数千条这样的消息,所以我很好奇JVM是否会优化实例分配(一段时间后)以避免每次都创建一个新实例

    class StatefullHandler implements MessageHandler {

    public void handle(final MyStartingMessage m) {
        m.setState(m.getUserId()); // used by the matchers
    }

    public void handle(final MyContinueMessage m) {
        // handle
    }

    // only returned for queries and never modified
    public Collection<MessageMatcher> matchers() {
        // message will only be handled by this instance if state matches
        // is this new operator optimized 'away' after some time??
        return ImmutableSet.of(MessageMatcher.for(MyContinueMessage.class, msg -> msg.getUserId())); 
    }
}
类StatefullHandler实现MessageHandler{
公共无效句柄(最终MyStartingMessage m){
m、 setState(m.getUserId());//由匹配器使用
}
公共无效句柄(最终mycontinuem消息){
//处理
}
//仅为查询返回,从不修改
公共集合匹配器(){
//只有状态匹配时,此实例才会处理消息
//这家新运营商是否在一段时间后“离开”进行了优化??
返回ImmutableSet.of(MessageMatcher.for(MyContinueMessage.class,msg->msg.getUserId());
}
}
如果没有优化,我实际上需要写以下内容:

class StatefullHandler implements MessageHandler {

    private static final MATCHERS = ImmutableSet.of(
        MessageMatcher.for(MyContinueMessage.class, msg -> msg.getUserId())); 

        public void handle(final MyStartingMessage m) {
            m.setState(m.getUserId()); // used by the matchers
        }

        public void handle(final MyContinueMessage m) {
            // handle
        }

        public Collection<MessageMatcher> matchers() {
            return MATCHERS;
        }
    }
类StatefullHandler实现MessageHandler{
私有静态最终匹配器=ImmutableSet.of(
MessageMatcher.for(MyContinueMessage.class,msg->msg.getUserId());
公共无效句柄(最终MyStartingMessage m){
m、 setState(m.getUserId());//由匹配器使用
}
公共无效句柄(最终mycontinuem消息){
//处理
}
公共集合匹配器(){
返回匹配器;
}
}

如果显式使用
new
关键字,JVM将无法重用旧的对象实例,因为这将违反Java语言规范。首先,当您通过
new
创建对象
A
B
时,可以保证
A==B
将返回
false
。其次,它保证您可以在
A
B
上独立地同步,而无需彼此等待。如果JVM重用旧对象,这将无法保证。因此,JVM甚至不能在最简单的情况下重用它们,例如
newinteger(1)


在某些情况下,您可以依赖第三方库执行的缓存,但在您的特定情况下,Guava的
ImmutableSet.of
仅对空集重用现有对象。因此,在您的情况下,使用
静态
字段似乎是最好的解决方案。

虽然JVM不能重用对象,但它可以首先避免创建它

如果在内联(即查看调用者及其调用者等)之后,对象以相同的方法生存和消亡,则可以将其放置在堆栈上,并可能使用转义分析消除

在您的情况下,完全有可能不会删除()的
对象,但也会删除lambda对象,这不会创建任何对象。这完全取决于您的用例以及优化器是否可以消除对象创建


我建议您使用商业探查器或飞行记录器来检查对象是否实际创建。

与Java 8中的远亲有很大关系,JVM很可能会优化对象分配。如果它能够证明您从未使用
a==B
或任何其他基于身份的操作,那么它可以。但是您无法从Java代码中证明它是否正确…