Home | History | Annotate | Download | only in hotspot_jni
      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_slow.d -c "java ..."
     40  *    2. CriticalSection_slow.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 self char *str_ptr;
     66 self string class_name;
     67 self string method_name;
     68 self string signature;
     69 
     70 self int indent;
     71 self int JAVA_STACK_DEEP;
     72 
     73 int CRITICAL_SECTION_VIOLATION_CNT;
     74 
     75 :::BEGIN
     76 {
     77     SAMPLE_NAME = "critical section violation checks";
     78 
     79     printf("BEGIN %s\n", SAMPLE_NAME);
     80 }
     81 
     82 hotspot$target:::*
     83 /!self->JAVA_STACK_DEEP/
     84 {
     85     self->JAVA_STACK_DEEP = 0;
     86 }
     87 
     88 
     89 hotspot$target:::method-return
     90 /self->JAVA_STACK_DEEP > 0/
     91 {
     92     self->JAVA_STACK_DEEP --;
     93 }
     94 
     95 hotspot$target:::method-entry
     96 {
     97     self->JAVA_STACK_DEEP ++;
     98 
     99     self->str_ptr = (char*) copyin(arg1, arg2+1);
    100     self->str_ptr[arg2] = '\0';
    101     self->method_name = strjoin( (string) self->str_ptr, ":");
    102 
    103     self->str_ptr = (char*) copyin(arg3, arg4+1);
    104     self->str_ptr[arg4] = '\0';
    105     self->method_name = strjoin(self->method_name, (string) self->str_ptr);
    106     self->method_name = strjoin(self->method_name, ":");
    107 
    108     self->str_ptr = (char*) copyin(arg5, arg6+1);
    109     self->str_ptr[arg6] = '\0';
    110     self->method_name = strjoin(self->method_name, (string) self->str_ptr);
    111 
    112     self->JAVA_STACK[self->JAVA_STACK_DEEP] = self->method_name;
    113 
    114 /*    printf("%-10u%*s%s\n",
    115  *      curcpu->cpu_id, self->indent, "", self->method_name);
    116  */
    117 }
    118 
    119 
    120 /*
    121  *   Multiple pairs of GetPrimitiveArrayCritical/ReleasePrimitiveArrayCritical,
    122  *   GetStringCritical/ReleaseStringCritical may be nested
    123  */
    124 hotspot_jni$target:::*_entry
    125 /self->in_critical_section > 0 &&
    126   probename != "GetPrimitiveArrayCritical_entry" &&
    127   probename != "GetStringCritical_entry" &&
    128   probename != "ReleasePrimitiveArrayCritical_entry" &&
    129   probename != "ReleaseStringCritical_entry" &&
    130   probename != "GetPrimitiveArrayCritical_return" &&
    131   probename != "GetStringCritical_return" &&
    132   probename != "ReleasePrimitiveArrayCritical_return" &&
    133   probename != "ReleaseStringCritical_return"/
    134 {
    135     printf("JNI call %s made from JNI critical region '%s' from %s\n",
    136         probename, self->critical_section_name,
    137         self->JAVA_STACK[self->JAVA_STACK_DEEP]);
    138 
    139     CRITICAL_SECTION_VIOLATION_CNT ++;
    140 }
    141 
    142 syscall:::entry
    143 /pid == $target && self->in_critical_section > 0/
    144 {
    145     printf("system call %s made in JNI critical region '%s' from %s\n",
    146         probefunc, self->critical_section_name,
    147         self->JAVA_STACK[self->JAVA_STACK_DEEP]);
    148 
    149     CRITICAL_SECTION_VIOLATION_CNT ++;
    150 }
    151 
    152 hotspot_jni$target:::ReleasePrimitiveArrayCritical_entry,
    153 hotspot_jni$target:::ReleaseStringCritical_entry
    154 /self->in_critical_section > 0/
    155 {
    156     self->in_critical_section --;
    157 }
    158 
    159 hotspot_jni$target:::GetPrimitiveArrayCritical_return
    160 {
    161     self->in_critical_section ++;
    162     self->critical_section_name = "GetPrimitiveArrayCritical";
    163 }
    164 
    165 hotspot_jni$target:::GetStringCritical_return
    166 {
    167     self->in_critical_section ++;
    168     self->critical_section_name = "GetStringCritical";
    169 }
    170 
    171 
    172 :::END
    173 {
    174     printf("%d critical section violations have been discovered\n",
    175         CRITICAL_SECTION_VIOLATION_CNT);
    176 
    177     printf("\nEND of %s\n", SAMPLE_NAME);
    178 }
    179