1 #!/usr/sbin/dtrace -Zs
2 
3 /*
4  * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  *   - Redistributions of source code must retain the above copyright
11  *     notice, this list of conditions and the following disclaimer.
12  *
13  *   - Redistributions in binary form must reproduce the above copyright
14  *     notice, this list of conditions and the following disclaimer in the
15  *     documentation and/or other materials provided with the distribution.
16  *
17  *   - Neither the name of Oracle nor the names of its
18  *     contributors may be used to endorse or promote products derived
19  *     from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
22  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
23  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
25  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 /*
35 */
36 
37 /*
38  * Usage:
39  *    1. CriticalSection.d -c "java ..."
40  *    2. CriticalSection.d -p JAVA_PID
41  *
42  * The script inspect a JNI application for Critical Section violations.
43  *
44  * Critical section is the space between calls to JNI methods:
45  *   - GetPrimitiveArrayCritical and ReleasePrimitiveArrayCritical; or
46  *   - GetStringCritical and ReleaseStringCritical.
47  *
48  * Inside a critical section, native code must not call other JNI functions,
49  * or any system call that may cause the current thread to block and wait
50  * for another Java thread. (For example, the current thread must not call
51  * read on a stream being written by another Java thread.)
52  *
53  */
54 
55 #pragma D option quiet
56 #pragma D option destructive
57 #pragma D option defaultargs
58 #pragma D option bufsize=16m
59 #pragma D option aggrate=100ms
60 
61 
62 self int in_critical_section;
63 self string critical_section_name;
64 
65 int CRITICAL_SECTION_VIOLATION_CNT;
66 
67 :::BEGIN
68 {
69     SAMPLE_NAME = "critical section violation checks";
70 
71     printf("BEGIN %s\n", SAMPLE_NAME);
72 }
73 
74 /*
75  *   Multiple pairs of GetPrimitiveArrayCritical/ReleasePrimitiveArrayCritical,
76  *   GetStringCritical/ReleaseStringCritical may be nested
77  */
78 hotspot_jni$target:::*_entry
79 /self->in_critical_section > 0 &&
80   probename != "GetPrimitiveArrayCritical_entry" &&
81   probename != "GetStringCritical_entry" &&
82   probename != "ReleasePrimitiveArrayCritical_entry" &&
83   probename != "ReleaseStringCritical_entry" &&
84   probename != "GetPrimitiveArrayCritical_return" &&
85   probename != "GetStringCritical_return" &&
86   probename != "ReleasePrimitiveArrayCritical_return" &&
87   probename != "ReleaseStringCritical_return"/
88 {
89     printf("\nJNI call %s made from JNI critical region '%s'\n",
90         probename, self->critical_section_name);
91 
92     printf("Jstack:\n");
93     jstack(50, 500);
94 
95     CRITICAL_SECTION_VIOLATION_CNT ++;
96 }
97 
98 syscall:::entry
99 /pid == $target && self->in_critical_section > 0/
100 {
101     printf("\nSystem call %s made in JNI critical region '%s'\n",
102         probefunc, self->critical_section_name);
103 
104     printf("Jstack:\n");
105     jstack(50, 500);
106 
107     CRITICAL_SECTION_VIOLATION_CNT ++;
108 }
109 
110 hotspot_jni$target:::ReleasePrimitiveArrayCritical_entry,
111 hotspot_jni$target:::ReleaseStringCritical_entry
112 /self->in_critical_section > 0/
113 {
114     self->in_critical_section --;
115 }
116 
117 hotspot_jni$target:::GetPrimitiveArrayCritical_return
118 {
119     self->in_critical_section ++;
120     self->critical_section_name = "GetPrimitiveArrayCritical";
121 }
122 
123 hotspot_jni$target:::GetStringCritical_return
124 {
125     self->in_critical_section ++;
126     self->critical_section_name = "GetStringCritical";
127 }
128 
129 
130 :::END
131 {
132     printf("%d critical section violations have been discovered\n",
133         CRITICAL_SECTION_VIOLATION_CNT);
134 
135     printf("\nEND of %s\n", SAMPLE_NAME);
136 }
137