1 #!/usr/sbin/dtrace -Zs
2 /*
3  * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  *   - Redistributions of source code must retain the above copyright
10  *     notice, this list of conditions and the following disclaimer.
11  *
12  *   - Redistributions in binary form must reproduce the above copyright
13  *     notice, this list of conditions and the following disclaimer in the
14  *     documentation and/or other materials provided with the distribution.
15  *
16  *   - Neither the name of Oracle nor the names of its
17  *     contributors may be used to endorse or promote products derived
18  *     from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
21  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 /*
34 */
35 
36 /*
37  * Usage:
38  *    1. class_loading_stat.d -c "java ..." INTERVAL_SECS
39  *    2. class_loading_stat.d -p JAVA_PID INTERVAL_SECS
40  *
41  * This script collects statistics about loaded and unloaded Java classes
42  * and dump current state to stdout every INTERVAL_SECS seconds.  If
43  * INTERVAL_SECS is not set then 10 seconds interval is used.
44  *
45  */
46 
47 #pragma D option quiet
48 #pragma D option destructive
49 #pragma D option defaultargs
50 #pragma D option aggrate=100ms
51 
52 
53 self char *str_ptr;
54 self string class_name;
55 self string package_name;
56 
57 int INTERVAL_SECS;
58 
59 :::BEGIN
60 {
61     SAMPLE_NAME = "hotspot class loadin tracing";
62 
63     INTERVAL_SECS = $1 ? $1 : 10;
64     SAMPLING_TIME = timestamp + INTERVAL_SECS * 1000000000ull;
65 
66     LOADED_CLASSES_CNT = 0;
67     UNLOADED_CLASSES_CNT = 0;
68 
69     LINE_SEP =
70     "------------------------------------------------------------------------";
71 
72     printf("BEGIN %s\n\n", SAMPLE_NAME);
73 }
74 
75 /*
76  * hotspot:::class-loaded, hotspot:::class-unloaded probe arguments:
77  *  arg0: char*,        class name passed as mUTF8 string
78  *  arg1: uintptr_t,    class name length
79  *  arg2: void*,        class loader ID, which is unique identifier for
80  *                      a class loader in the VM.
81  *  arg3: uintptr_t,    class is shared or not
82  */
83 hotspot$target:::class-loaded
84 {
85     LOADED_CLASSES_CNT ++;
86 
87     self->str_ptr = (char*) copyin(arg0, arg1+1);
88     self->str_ptr[arg1] = '\0';
89     self->class_name = (string) self->str_ptr;
90 
91     self->package_name = dirname(self->class_name);
92 
93     @classes_loaded[self->package_name] = count();
94 }
95 
96 hotspot$target:::class-unloaded
97 {
98     UNLOADED_CLASSES_CNT ++;
99 
100     self->str_ptr = (char*) copyin(arg0, arg1+1);
101     self->str_ptr[arg1] = '\0';
102     self->class_name = (string) self->str_ptr;
103 
104     self->package_name = dirname(self->class_name);
105 
106     @classes_unloaded[self->package_name] = count();
107 }
108 
109 
110 tick-1sec
111 /timestamp > SAMPLING_TIME/
112 {
113     printf("%s\n", LINE_SEP);
114     printf("%Y\n", walltimestamp);
115     printf("%s\n", LINE_SEP);
116 
117     printf("Loaded classes by package:\n");
118     printa("%10@d %s\n", @classes_loaded);
119 
120     printf("\n");
121     printf("Unloaded classes by package:\n");
122     printa("%10@d %s\n", @classes_unloaded);
123 
124     printf("\n");
125     printf("Number of loaded classes: %10d\n", LOADED_CLASSES_CNT);
126     printf("Number of unloaded classes: %10d\n", UNLOADED_CLASSES_CNT);
127 
128     SAMPLING_TIME = timestamp + INTERVAL_SECS * 1000000000ull;
129 }
130 
131 
132 :::END
133 {
134     printf("%s\n", LINE_SEP);
135     printf("%Y\n", walltimestamp);
136     printf("%s\n", LINE_SEP);
137 
138     printf("Loaded classes by package:\n");
139     printa("%10@d %s\n", @classes_loaded);
140 
141     printf("\n");
142     printf("Unloaded classes by package:\n");
143     printa("%10@d %s\n", @classes_unloaded);
144 
145     printf("\n");
146     printf("Number of loaded classes: %10d\n", LOADED_CLASSES_CNT);
147     printf("Number of unloaded classes: %10d\n", UNLOADED_CLASSES_CNT);
148 
149     printf("\nEND of %s\n", SAMPLE_NAME);
150 }
151 
152 syscall::rexit:entry,
153 syscall::exit:entry
154 /pid == $target/
155 {
156    exit(0);
157 }
158