[英]Unusual Java behavior - why does this work?
我发现了一些有趣的行为......我无法确定这是错误还是无能,但目前倾向于无能。
这段代码不会进入循环,即使有消息在等待:
Message msg;
while ((msg = consumer.receiveNoWait()) != null) {
System.out.println(msg);
}
此代码确实进入了循环,请注意 null 分配:
Message msg = null;
while ((msg = consumer.receiveNoWait()) != null) {
System.out.println(msg);
}
此代码在 Windows 32 位上的 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();
}
最后,我说的是我自己的无能。 ;)
正如瑞安所说,这似乎是一种竞赛条件。 两个代码的字节码是相同的,除了一个额外的“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
}
如果你想测试这个理论,试试这个代码:
Message msg;
String dummy = null;
while ((msg = consumer.receiveNoWait()) != null) {
System.out.println(msg);
}
这是一个 noop,但字节码与第二个代码几乎相同(将“astore_0”更改为“astore_1”)。
顺便说一句,我用“receiveNoWait”得到了可怕的结果。 我更喜欢“receive(smallTimeout)”,以避免缓冲区不足等。
这对我来说听起来像是一种竞争条件。 没有实例化的对象声明将始终导致 null 值。 您可能认为在第一种情况下有消息在等着您,但我敢打赌没有。 在条件循环之前,打印出对象的数量并验证结果行为。 如果您处于多线程情况,请在必要时在消息队列上同步以促进此操作。 我敢打赌它会完全按预期工作。
我的钱是你没有运行你认为的代码。 您提到“在 Glassfish 3.1.1b10 上运行”,因此单元测试的方式可能并不多,因此查明错误所在位置的能力变得更加困难。
在一些奇怪的边缘情况下,有几种可能性可能会有所不同。
null
assignment clobbers a reference on the stack, which allows an object to be be garbage collected that references an object that is used with a weak/soft/phantom/finaliser reference, or perhaps just changes memory allocation timings and disturbs a race condition.您是否可以提供消费者 oject 可能是什么以及 receiveNoWait() 可能是什么?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.