不寻常的Java行为 - 为什么这样做?

Jon*_*her 9 java jms java-ee

我发现了一些有趣的行为......我无法确定这是一个错误还是无能,但目前倾向于无能.

即使有消息等待,此代码也不会进入循环:

Message msg;
while ((msg = consumer.receiveNoWait()) != null) {
    System.out.println(msg);
}
Run Code Online (Sandbox Code Playgroud)

此代码进入循环,注意空赋值:

Message msg = null;
while ((msg = consumer.receiveNoWait()) != null) {
    System.out.println(msg);
}
Run Code Online (Sandbox Code Playgroud)

此代码在Windows 32bit上的Glassfish 3.1.1b10 HotSpot 1.6_26上运行.我想不出为什么第一个块不起作用的解释!

编辑/更新2011年7月13日:

首先,我开始停止Glassfish域并在每个请求的部署之间删除它,这仍然会发生:)

其次,我无法在Destination或Consumer上同步,因为这是Java EE代码.但是,我可以保证有可用的消息.其中大约有500个没有消费者.事实上,创建QueueBrowser告诉我有可用的消息!

第三,这个程序打印"WORKS!" 每次!!!哎呀!

public static void main(String[] args) {
    Object obj;

    if ((obj = getNotNull()) != null) {
        System.out.println("worked!");
    } else {
        System.out.println("failed!");
    }
}

static Object getNotNull() {
    return new Object();
}
Run Code Online (Sandbox Code Playgroud)

最后,我说的是我自己的无能.;)

Edu*_*sta 3

正如瑞安所说,这似乎是一种竞争条件。两个代码的字节码是相同的,除了一个额外的“astore”:

public static void code1()   throws javax.jms.JMSException;
  Code:
   0:   getstatic   #2; //Field consumer:Ljavax/jms/MessageConsumer;
   3:   invokeinterface #3,  1; //InterfaceMethod javax/jms/MessageConsumer.receiveNoWait:()Ljavax/jms/Message;
   8:   dup
   9:   astore_0
   10:  ifnull  23
   13:  getstatic   #4; //Field java/lang/System.out:Ljava/io/PrintStream;
   16:  aload_0
   17:  invokevirtual   #5; //Method java/io/PrintStream.println:(Ljava/lang/Object;)V
   20:  goto    0
   23:  return

public static void code2()   throws javax.jms.JMSException;
  Code:
   0:   aconst_null
   1:   astore_0
   2:   getstatic   #2; //Field consumer:Ljavax/jms/MessageConsumer;
   5:   invokeinterface #3,  1; //InterfaceMethod javax/jms/MessageConsumer.receiveNoWait:()Ljavax/jms/Message;
   10:  dup
   11:  astore_0
   12:  ifnull  25
   15:  getstatic   #4; //Field java/lang/System.out:Ljava/io/PrintStream;
   18:  aload_0
   19:  invokevirtual   #5; //Method java/io/PrintStream.println:(Ljava/lang/Object;)V
   22:  goto    2
   25:  return

}
Run Code Online (Sandbox Code Playgroud)

如果您想测试这个理论,请尝试以下代码:

Message msg;
String dummy = null;
while ((msg = consumer.receiveNoWait()) != null) {
    System.out.println(msg);
}
Run Code Online (Sandbox Code Playgroud)

这是一个 noop,但字节码几乎与第二个代码相同(将“astore_0”更改为“astore_1”)。

顺便说一句,我的“receiveNoWait”结果很糟糕。我更喜欢“receive(smallTimeout)”,以避免缓冲区欠载等。