[英]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.