[prev in list] [next in list] [prev in thread] [next in thread] 

List:       openjdk-hotspot-runtime-dev
Subject:    =?gb2312?B?tPC4tDogtPC4tDogSG90U3BvdCBhbmQgSUJNJ3MgSjkgYmVoYXZlIA==?= =?gb2312?B?cXVpdGUgZGlmZmVyZW5
From:       <chenyt () cs ! sjtu ! edu ! cn>
Date:       2017-05-18 5:26:39
Message-ID: 000001d2cf97$54ba6a00$fe2f3e00$ () cs ! sjtu ! edu ! cn
[Download RAW message or body]

Hi, David,

I tested the next Jimple programs (let one object under monitoring be null)
using J9 and HotSpot. I did not see NullPointerException here (the
specification does tell me so when an object reference is null). Am I wrong
again? Hope the next two cases will help check.

(1) case 1: HotSpot: IllegalMonitorStateException J9: NullPointerException
        r0 := @this: Search;
        r1 := @parameter0: java.lang.String[];
        r2 = null;
        entermonitor r0;
        entermonitor r2;
        exitmonitor r2;
        exitmonitor r0;
 (2) case 2: HotSpot: IllegalMonitorStateException J9: VerifyError
        r1 := @parameter0: java.lang.String[];
        r2 = new Search;
        entermonitor r0;
        entermonitor r2;
        r2=null;
        exitmonitor r2;
        exitmonitor r0;
It is very interesting that I can still find some unexpected behaviors here.

Wishes,
Yuting-----ÓʼþÔ­¼þ-----
·¢¼þÈË: ³ Óêͤ [mailto:chenyt@cs.sjtu.edu.cn] 
·¢ËÍʱ¼ä: 2017Äê5Ô 17ÈÕ 21:18
ÊÕ¼þÈË: 'David Holmes' <david.holmes@oracle.com>;
'hotspot-runtime-dev@openjdk.java.net'
<hotspot-runtime-dev@openjdk.java.net>
Ö÷Ìâ: ´ð¸´: ´ð¸´: HotSpot and IBM's J9 behave quite differently when
processing monitorenters and monitorexits

Hi, David,

I still did not catch why it happens... I just read the specification and
wrote some tests in order to understand some paragraphs better, and then had
questions. 

Will the HotSpot's verifier detect such kind of uninitialized monitored
objects in future?

Regards,
Yuting

-----ÓʼþÔ­¼þ-----
·¢¼þÈË: David Holmes [mailto:david.holmes@oracle.com]
·¢ËÍʱ¼ä: 2017Äê5Ô 17ÈÕ 20:23
ÊÕ¼þÈË: ³ Óêͤ <chenyt@cs.sjtu.edu.cn>; hotspot-runtime-dev@openjdk.java.net
Ö÷Ìâ: Re: ´ð¸´: HotSpot and IBM's J9 behave quite differently when
processing monitorenters and monitorexits

One correction ...

On 18/05/2017 10:29 AM, David Holmes wrote:
> On 18/05/2017 8:12 AM, ³ Óêͤ wrote:
>> Thank you, David. I have seen from the specification that structured 
>> locking enforcement is optional. The second and the third ones are 
>> cases of structured/nested lockings. Will non-nested locking 
>> sequences raise deadlocks? Of course it is a different topic, while 
>> it might be better if it can be kicked out earlier from the 
>> specification/JVM.
>
> Non-nested locking doesn't necessarily lead to deadlocks - you just 
> need a different locking order for that (even if properly nested).
> There are locking patterns that rely on the ability to lock and unlock 
> in different order ie chained-locking for walking linked-lists A->B->C->D:
> - lock A, lock B, unlock A, lock C, unlock B, lock D, unlock C ...
>
> The VM spec allows a little flexibility in how the monitor bytecodes 
> can be used compared to the Java programming language. That's not 
> something that will change.
>
>> The first example is still a problem. It seems that HotSpot allows to 
>> monitor a pure object reference without initialized (Is it true? How 
>> can this checking be omitted?). J9 reports a verifyerror as follows.
>>
>> Exception in thread "main" java.lang.VerifyError: JVMVRFY012 stack 
>> shape inconsistent; class=Search, method=main([Ljava/lang/String;)V,
>> pc=6 Exception Details:
>>   Location:
>>     Search.main([Ljava/lang/String;)V @6: JBmonitorenter
>>   Reason:
>>     Type 'uninitialized' (current frame, stack[1]) is not assignable 
>> to 'java/lang/Object'
>>   Current Frame:
>>     bci: @6
>>     flags: { }
>>     locals: { 'Search', '[Ljava/lang/String;' }
>>     stack: { 'uninitialized', 'uninitialized' }
>>     at T.main(T.java:4)
>
> Yes I think this may be a bug in hotspot. The type-checking for the 
> monitor bytecodes requires a matching type of reference on the operand 
> stack - but "uninitialized" does not match Object, as J9 reports. But 
> I'm not an expert on this aspect of verification so I may not be 
> interpreting it correctly.
>
> More below ...
>
>> -----ÓʼþÔ­¼þ-----
>> ·¢¼þÈË: David Holmes [mailto:david.holmes@oracle.com]
>> ·¢ËÍʱ¼ä: 2017Äê5Ô 17ÈÕ 14:41
>> ÊÕ¼þÈË: ³ Óêͤ <chenyt@cs.sjtu.edu.cn>;
>> hotspot-runtime-dev@openjdk.java.net
>> Ö÷Ìâ: Re: HotSpot and IBM's J9 behave quite differently when processing 
>> monitorenters and monitorexits
>>
>> Hi,
>> On 18/05/2017 7:23 AM, ³ Óêͤ wrote:
>>> Am I wrong?
>>
>> I will look at each situation in detail when I get a chance but 
>> structured locking enforcement is optional. Also balancing the number 
>> of locks and unlocks in a frame does not mean they can't be locked 
>> and unlocked in a non-nested fashion - just that by the end the 
>> number of unlocks matches the number of locks.
>>
>> BTW the way you respond to these emails, as if having a conversation 
>> with yourself, makes it difficult to respond as we can't readily see 
>> what is the new email and what is the original.
>>
>> Cheers,
>> David
>>
>>> The byte code for main() in case 1 is as follows. The strange thing 
>>> is that NullPointerException is also not thrown at runtime.
>
> That is strange as it does for the normal obvious case of using
> synchronized(o) when o is null.

Ah - it isn't null it just an object for which the constructor has not been
run. The runtime can't tell the difference between a pointer to a valid
initialized object, and a pointer to an uninitialized chunk of memory.

>>>
>>> public void main(java.lang.String[]) throws java.lang.Exception;
>>>     descriptor: ([Ljava/lang/String;)V
>>>     flags: ACC_PUBLIC
>>>     Code:
>>>       stack=3, locals=2, args_size=2
>>>          0: new           #2                  // class Search

This allocated an object - hence no null reference. But this is what
verification should have complained about.

David
-----

>>>          3: dup
>>>          4: aload_0
>>>          5: monitorenter
>>>          6: monitorenter
>>>          7: monitorexit
>>>          8: aload_0
>>>          9: monitorexit
>>>         10: return
>>>     Exceptions:
>>>       throws java.lang.Exception
>>>
>>> Ö÷Ìâ: HotSpot and IBM's J9 behave quite differently when processing 
>>> monitorenters and monitorexits
>>>
>>> I have tested several programs (in Jimple) and found that HotSpot 
>>> and
>>> J9 match monitorenters and monitorexits quite differently. Verifiers 
>>> should play more important roles here.
>
> The job of the verifier is to establish some basic guarantees for the 
> JVM to then operate under. The verifier plays no role in checking how 
> monitorenter/exit are used in combination, only that each individual 
> bytecode meets some basic type constraints.
>
>>>
>>> (1) Test the next program (r2 is not initizlied) on HotSpot and J9.
>>> J9 throw out a verifier error, while HotSpot does not. It seems that 
>>> HotSpot's verifier forgets to check whether a monitored object is 
>>> initialized.
>>>
>>> public class Search extends java.lang.Object { public void <init>()
>>>     {
>>>         Search r0;
>>>         r0 := @this: Search;
>>>         specialinvoke r0.<java.lang.Object: void <init>()>();
>>>         return;
>>>     }
>>> public void main(java.lang.String[]) throws java.lang.Exception
>>>     {
>>>         Search r0;
>>>         Search r2;
>>>         java.lang.String[] r1;
>>>         r0 := @this: Search;
>>>         r1 := @parameter0: java.lang.String[];
>>>         r2 = new Search;
>>>
>>>         entermonitor r2;
>>>         entermonitor r0;
>>>         exitmonitor r2;
>>>         exitmonitor r0;
>>>         return;
>>>     }
>>> }
>
> Verification was covered above.
>
>>>
>>> (2) Test the next program on HotSpot and J9, and both do not report 
>>> any errors. However, I guess the order in the program (entermonitor 
>>> r2; => entermonitor r0; =>  exitmonitor r2; => exitmonitor r0;) 
>>> violates the situation of "structured locking" (Structured locking 
>>> is the situation when, during a method invocation, every exit on a 
>>> given monitor matches a preceding entry on that monitor, see the 
>>> specification 
>>> https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-2.html#jvms-2.
>>> 11.10)
>>> ?
>
> No it doesn't violate structured locking as the number of enters and 
> exits match, and there is always an enter before an exit.
>
>>> Actually, the words (every exit on a given monitor matches a 
>>> preceding entry on that monitor) are not quite clear as for me.
>>> Otherwise the first rule (The number of monitor entries performed by 
>>> T on M during a method invocation must equal the number of monitor 
>>> exits performed by T on M during the method invocation whether the 
>>> method  invocation completes normally or abruptly.) is sufficient.
>
> The number of enters and exits must not only match/balance, but there 
> must be an enter before a corresponding exit.
>
>>>
>>> public class Search extends java.lang.Object {
>>>
>>> public void <init>()
>>>     {
>>>         Search r0;
>>>         r0 := @this: Search;
>>>         specialinvoke r0.<java.lang.Object: void <init>()>();
>>>         return;
>>>     }
>>>
>>> public void main(java.lang.String[]) throws java.lang.Exception
>>>     {
>>>         Search r0;
>>>         Search r2;
>>>         java.lang.String[] r1;
>>>         r0 := @this: Search;
>>>         r1 := @parameter0: java.lang.String[];
>>>         r2 = new Search;
>>>         specialinvoke r2.<Search: void <init>()>();
>>>         entermonitor r2;
>>>         entermonitor r0;
>>>         exitmonitor r2;
>>>         exitmonitor r0;
>>>         return;
>>>     }
>>> }
>>>
>>> (3) The next program enters monitor in <init> and exits it in main().
>>> HotSpot throws a runtime exception, while J9 does not. Should this 
>>> program be rejected by the verifiers?
>
> No this does not violate any verification rules. The runtime behaviour 
> depends on whether structured locking is enforced or not.(Even in 
> hotspot there can be differences between interpreted and jitted code).
>
> Hope that helps clarify things.
>
> David
> -----
>
>>>
>>> public class Search extends java.lang.Object {
>>>
>>> public void <init>()
>>>     {
>>>         Search r0;
>>>         r0 := @this: Search;
>>>         specialinvoke r0.<java.lang.Object: void <init>()>();
>>>         entermonitor r0;
>>>         return;
>>>     }
>>>
>>> public void main(java.lang.String[]) throws java.lang.Exception
>>>     {
>>>         Search r0;
>>>         Search r2;
>>>         java.lang.String[] r1;
>>>         r0 := @this: Search;
>>>         r1 := @parameter0: java.lang.String[];
>>>         r2 = new Search;
>>>         specialinvoke r2.<Search: void <init>()>();
>>>         exitmonitor r2;
>>>         exitmonitor r0;
>>>         return;
>>>     }
>>> }
>>>
>>>
>>

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic