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