#!/usr/sbin/dtrace -Zs
/*
* Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
*/
/*
* Usage:
* 1. class_loading_stat.d -c "java ..." INTERVAL_SECS
* 2. class_loading_stat.d -p JAVA_PID INTERVAL_SECS
*
* This script collects statistics about loaded and unloaded Java classes
* and dump current state to stdout every INTERVAL_SECS seconds. If
* INTERVAL_SECS is not set then 10 seconds interval is used.
*
*/
#pragma D option quiet
#pragma D option destructive
#pragma D option defaultargs
#pragma D option aggrate=100ms
self char *str_ptr;
self string class_name;
self string package_name;
int INTERVAL_SECS;
:::BEGIN
{
SAMPLE_NAME = "hotspot class loadin tracing";
INTERVAL_SECS = $1 ? $1 : 10;
SAMPLING_TIME = timestamp + INTERVAL_SECS * 1000000000ull;
LOADED_CLASSES_CNT = 0;
UNLOADED_CLASSES_CNT = 0;
LINE_SEP =
"------------------------------------------------------------------------";
printf("BEGIN %s\n\n", SAMPLE_NAME);
}
/*
* hotspot:::class-loaded, hotspot:::class-unloaded probe arguments:
* arg0: char*, class name passed as mUTF8 string
* arg1: uintptr_t, class name length
* arg2: void*, class loader ID, which is unique identifier for
* a class loader in the VM.
* arg3: uintptr_t, class is shared or not
*/
hotspot$target:::class-loaded
{
LOADED_CLASSES_CNT ++;
self->str_ptr = (char*) copyin(arg0, arg1+1);
self->str_ptr[arg1] = '\0';
self->class_name = (string) self->str_ptr;
self->package_name = dirname(self->class_name);
@classes_loaded[self->package_name] = count();
}
hotspot$target:::class-unloaded
{
UNLOADED_CLASSES_CNT ++;
self->str_ptr = (char*) copyin(arg0, arg1+1);
self->str_ptr[arg1] = '\0';
self->class_name = (string) self->str_ptr;
self->package_name = dirname(self->class_name);
@classes_unloaded[self->package_name] = count();
}
tick-1sec
/timestamp > SAMPLING_TIME/
{
printf("%s\n", LINE_SEP);
printf("%Y\n", walltimestamp);
printf("%s\n", LINE_SEP);
printf("Loaded classes by package:\n");
printa("%10@d %s\n", @classes_loaded);
printf("\n");
printf("Unloaded classes by package:\n");
printa("%10@d %s\n", @classes_unloaded);
printf("\n");
printf("Number of loaded classes: %10d\n", LOADED_CLASSES_CNT);
printf("Number of unloaded classes: %10d\n", UNLOADED_CLASSES_CNT);
SAMPLING_TIME = timestamp + INTERVAL_SECS * 1000000000ull;
}
:::END
{
printf("%s\n", LINE_SEP);
printf("%Y\n", walltimestamp);
printf("%s\n", LINE_SEP);
printf("Loaded classes by package:\n");
printa("%10@d %s\n", @classes_loaded);
printf("\n");
printf("Unloaded classes by package:\n");
printa("%10@d %s\n", @classes_unloaded);
printf("\n");
printf("Number of loaded classes: %10d\n", LOADED_CLASSES_CNT);
printf("Number of unloaded classes: %10d\n", UNLOADED_CLASSES_CNT);
printf("\nEND of %s\n", SAMPLE_NAME);
}
syscall::rexit:entry,
syscall::exit:entry
/pid == $target/
{
exit(0);
}