/*
* Licensed to the Apache Software Foundation ( ASF ) under one
* or more contributor license agreements . See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership . The ASF licenses this file
* to you under the Apache License , Version 2 . 0 ( the
* " License " ) ; you may not use this file except in compliance
* with the License . You may obtain a copy of the License at
*
* http : //www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing ,
* software distributed under the License is distributed on an
* " AS IS " BASIS , WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND , either express or implied . See the License for the
* specific language governing permissions and limitations
* under the License .
*/
/*
* author Ian Formanek
* Misha Dmitriev
* Tomas Hurka
*/
#ifdef WIN32
#include <Windows.h>
#else
#include <sys/time.h>
#include <fcntl.h>
#include <time.h>
#endif
#ifdef SOLARIS
#define _STRUCTURED_PROC 1
#include <sys/procfs.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "jni.h"
#include "jvmti.h"
#include "org_netbeans_lib_profiler_server_system_Threads.h"
#include "common_functions.h"
/* The following is copied from org.netbeans.lib.profiler.global.CommonConstants */
#define THREAD_STATUS_UNKNOWN -1
#define THREAD_STATUS_ZOMBIE 0
#define THREAD_STATUS_RUNNING 1
#define THREAD_STATUS_SLEEPING 2
#define THREAD_STATUS_MONITOR 3
#define THREAD_STATUS_WAIT 4
#define THREAD_STATUS_PARK 5
/* These masks essentially map JVMTI thread states into the above states */
static jint JF_THREAD_STATE_MASK = JVMTI_THREAD_STATE_TERMINATED |
JVMTI_THREAD_STATE_ALIVE |
JVMTI_THREAD_STATE_RUNNABLE |
JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER |
JVMTI_THREAD_STATE_WAITING |
JVMTI_THREAD_STATE_WAITING_INDEFINITELY |
JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT |
JVMTI_THREAD_STATE_SLEEPING |
JVMTI_THREAD_STATE_PARKED;
static jint JF_THREAD_STATE_NEW = 0 ;
static jint JF_THREAD_STATE_TERMINATED = JVMTI_THREAD_STATE_TERMINATED;
static jint JF_THREAD_STATE_RUNNABLE = JVMTI_THREAD_STATE_ALIVE |
JVMTI_THREAD_STATE_RUNNABLE;
static jint JF_THREAD_STATE_BLOCKED = JVMTI_THREAD_STATE_ALIVE |
JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER;
static jint JF_THREAD_STATE_WAITING = JVMTI_THREAD_STATE_ALIVE |
JVMTI_THREAD_STATE_WAITING |
JVMTI_THREAD_STATE_WAITING_INDEFINITELY;
static jint JF_THREAD_STATE_TIMED_WAITING = JVMTI_THREAD_STATE_ALIVE |
JVMTI_THREAD_STATE_WAITING |
JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT;
static jint JF_THREAD_STATE_SLEEPING = JVMTI_THREAD_STATE_ALIVE |
JVMTI_THREAD_STATE_WAITING |
JVMTI_THREAD_STATE_SLEEPING |
JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT;
static jint JF_THREAD_STATE_TIMED_PARKED = JVMTI_THREAD_STATE_ALIVE |
JVMTI_THREAD_STATE_WAITING |
JVMTI_THREAD_STATE_PARKED |
JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT;
static jint JF_THREAD_STATE_PARKED = JVMTI_THREAD_STATE_ALIVE |
JVMTI_THREAD_STATE_WAITING |
JVMTI_THREAD_STATE_PARKED |
JVMTI_THREAD_STATE_WAITING_INDEFINITELY;
static int nProfThreads;
static jthread *profThreads = NULL;
static jthread mainThread = NULL, singleProfThread = NULL, additionalProfThread = NULL;
static jclass threadType = NULL;
jint convert_JVMTI_thread_status_to_jfluid_status(jint jvmtiThreadStatus) {
jint status = jvmtiThreadStatus & JF_THREAD_STATE_MASK;
if (status == JF_THREAD_STATE_RUNNABLE) return THREAD_STATUS_RUNNING;
else if (status == JF_THREAD_STATE_BLOCKED) return THREAD_STATUS_MONITOR;
else if (status == JF_THREAD_STATE_WAITING) return THREAD_STATUS_WAIT;
else if (status == JF_THREAD_STATE_TIMED_WAITING) return THREAD_STATUS_WAIT;
else if (status == JF_THREAD_STATE_PARKED) return THREAD_STATUS_PARK;
else if (status == JF_THREAD_STATE_TIMED_PARKED) return THREAD_STATUS_PARK;
else if (status == JF_THREAD_STATE_SLEEPING) return THREAD_STATUS_SLEEPING;
else if (status == JF_THREAD_STATE_NEW) return THREAD_STATUS_ZOMBIE;
else if (status == JF_THREAD_STATE_TERMINATED) return THREAD_STATUS_ZOMBIE;
else return THREAD_STATUS_UNKNOWN;
}
static int isProfilerThread(JNIEnv *env, jthread thread) {
int i;
if (additionalProfThread != NULL) {
if ((*env)->IsSameObject(env, thread, additionalProfThread)) {
return 1 ;
}
}
if (profThreads != NULL) {
for (i = 0 ; i < nProfThreads; i++) {
if ((*env)->IsSameObject(env, thread, profThreads[i])) return 1 ;
}
return 0 ;
} else {
return ((*env)->IsSameObject(env, thread, singleProfThread));
}
}
/*
* Class : org_netbeans_lib_profiler_server_system_Threads
* Method : recordProfilerOwnThreads
* Signature : ( ZLjava / lang / Thread ; ) I
*/
JNIEXPORT jint JNICALL Java_org_netbeans_lib_profiler_server_system_Threads_recordProfilerOwnThreads
(JNIEnv *env, jclass clz, jboolean excludeSpecialThread, jobject specialThread)
{
jvmtiError res;
int i, j;
if (profThreads != NULL) {
for (i = 0 ; i < nProfThreads; i++) {
(*env)->DeleteGlobalRef(env, profThreads[i]);
}
(*_jvmti)->Deallocate(_jvmti, (unsigned char *) profThreads);
}
profThreads = NULL;
if (singleProfThread != NULL) {
(*env)->DeleteGlobalRef(env, singleProfThread);
}
singleProfThread = NULL;
if (mainThread != NULL) {
(*env)->DeleteGlobalRef(env, mainThread);
}
mainThread = NULL;
if (excludeSpecialThread) {
res = (*_jvmti)->GetAllThreads(_jvmti, (jint*)&nProfThreads, &profThreads);
assert(res == JVMTI_ERROR_NONE);
if (specialThread != NULL) {
for (i = 0 ; i < nProfThreads; i++) {
if ((*env)->IsSameObject(env, specialThread, profThreads[i])) {
for (j = i+1 ; j < nProfThreads; j++) {
profThreads[j-1 ] = profThreads[j];
}
nProfThreads--;
break ;
}
}
mainThread = (*env)->NewGlobalRef(env, specialThread);
}
/* Results were returned as local references; make them global to survive across native calls */
for (i = 0 ; i < nProfThreads; i++) {
profThreads[i] = (*env)->NewGlobalRef(env, profThreads[i]);
}
return nProfThreads;
} else {
singleProfThread = (*env)->NewGlobalRef(env, specialThread);
return 1 ;
}
}
/*
* Class : org_netbeans_lib_profiler_server_system_Threads
* Method : recordAdditionalProfilerOwnThread
* Signature : ( Ljava / lang / Thread ; ) V
*/
JNIEXPORT void JNICALL Java_org_netbeans_lib_profiler_server_system_Threads_recordAdditionalProfilerOwnThread
(JNIEnv *env, jclass clz, jobject specialThread)
{
if (additionalProfThread != NULL) {
(*env)->DeleteGlobalRef(env, additionalProfThread);
}
additionalProfThread = (*env)->NewGlobalRef(env, specialThread);
}
/*
* Class : org_netbeans_lib_profiler_server_system_Threads
* Method : getTotalNumberOfThreads
* Signature : ( ) I
*/
JNIEXPORT jint JNICALL Java_org_netbeans_lib_profiler_server_system_Threads_getTotalNumberOfThreads
(JNIEnv *env, jclass clz)
{
jvmtiError res;
int nThreads;
jthread *threads = NULL;
res = (*_jvmti)->GetAllThreads(_jvmti, (jint*)&nThreads, &threads);
assert(res == JVMTI_ERROR_NONE);
if (threads != NULL) {
(*_jvmti)->Deallocate(_jvmti, (unsigned char *) threads);
}
return nThreads;
}
/*
* Class : org_netbeans_lib_profiler_server_system_Threads
* Method : suspendTargetAppThreads
* Signature : ( Ljava / lang / Thread ; ) V
*/
JNIEXPORT void JNICALL Java_org_netbeans_lib_profiler_server_system_Threads_suspendTargetAppThreads
(JNIEnv *env, jclass clz, jobject excludedThread)
{
jvmtiError res;
int i;
int nThreads;
jthread *threads = NULL;
res = (*_jvmti)->GetAllThreads(_jvmti, (jint*)&nThreads, &threads);
assert(res == JVMTI_ERROR_NONE);
for (i = 0 ; i < nThreads; i++) {
if (! (isProfilerThread(env, threads[i]) || (*env)->IsSameObject(env, excludedThread, threads[i]))) {
(*_jvmti)->SuspendThread(_jvmti, threads[i]);
}
}
(*_jvmti)->Deallocate(_jvmti, (unsigned char *) threads);
}
/*
* Class : org_netbeans_lib_profiler_server_system_Threads
* Method : resumeTargetAppThreads
* Signature : ( Ljava / lang / Thread ; ) V
*/
JNIEXPORT void JNICALL Java_org_netbeans_lib_profiler_server_system_Threads_resumeTargetAppThreads
(JNIEnv *env, jclass clz, jobject excludedThread)
{
jvmtiError res;
int i;
int nThreads;
jthread *threads = NULL;
res = (*_jvmti)->GetAllThreads(_jvmti, (jint*)&nThreads, &threads);
assert(res == JVMTI_ERROR_NONE);
for (i = 0 ; i < nThreads; i++) {
if (! (isProfilerThread(env, threads[i]) || (*env)->IsSameObject(env, excludedThread, threads[i]))) {
(*_jvmti)->ResumeThread(_jvmti, threads[i]);
}
}
(*_jvmti)->Deallocate(_jvmti, (unsigned char *) threads);
}
/*
* Class : org_netbeans_lib_profiler_server_system_Threads
* Method : terminateTargetAppThreads
* Signature : ( Ljava / lang / Object ; ) V
*/
JNIEXPORT void JNICALL Java_org_netbeans_lib_profiler_server_system_Threads_terminateTargetAppThreads
(JNIEnv *env, jclass clz, jobject excObject)
{
jvmtiError res;
int i;
int nThreads;
jthread *threads;
res = (*_jvmti)->GetAllThreads(_jvmti, (jint*)&nThreads, &threads);
assert(res == JVMTI_ERROR_NONE);
for (i = 0 ; i < nThreads; i++) {
if (! isProfilerThread(env, threads[i])) {
(*_jvmti)->StopThread(_jvmti, threads[i], excObject);
}
}
(*_jvmti)->Deallocate(_jvmti, (unsigned char *) threads);
if (mainThread != NULL) {
(*env)->DeleteGlobalRef(env, mainThread);
}
mainThread = NULL;
}
/*
* Class : org_netbeans_lib_profiler_server_system_Threads
* Method : targetAppThreadsExist
* Signature : ( ) Z
*/
JNIEXPORT jboolean JNICALL Java_org_netbeans_lib_profiler_server_system_Threads_targetAppThreadsExist
(JNIEnv *env, jclass clz)
{
jvmtiError res;
int i;
jboolean exist;
int nThreads;
jthread *threads;
res = (*_jvmti)->GetAllThreads(_jvmti, (jint*)&nThreads, &threads);
assert(res == JVMTI_ERROR_NONE);
exist = 0 ;
for (i = 0 ; i < nThreads; i++) {
if (! isProfilerThread(env, threads[i]) && ! (*env)->IsSameObject(env, threads[i], mainThread)) {
exist = 1 ;
break ;
}
}
(*_jvmti)->Deallocate(_jvmti, (unsigned char *) threads);
return exist;
}
/*
* Class : org_netbeans_lib_profiler_server_system_Threads
* Method : getAllThreads
* Signature : ( [ Ljava / lang / Thread ; ) [ Ljava / lang / Thread ;
*/
JNIEXPORT jobjectArray JNICALL Java_org_netbeans_lib_profiler_server_system_Threads_getAllThreads
(JNIEnv *env , jclass clz, jobjectArray jthreads)
{
int nThreads, arrayLen, i;
jthread *threads = NULL;
jvmtiError res;
res = (*_jvmti)->GetAllThreads(_jvmti, (jint*)&nThreads, &threads);
assert(res == JVMTI_ERROR_NONE);
arrayLen = (jthreads != NULL) ? (*env)->GetArrayLength(env, jthreads) : 0 ;
if (nThreads > arrayLen) {
if (threadType == NULL) {
threadType = (*env)->FindClass(env, "java/lang/Thread" );
threadType = (*env)->NewGlobalRef(env, threadType);
}
jthreads = (*env)->NewObjectArray(env, nThreads, threadType, NULL);
}
for (i = 0 ; i < nThreads; i++) {
(*env)->SetObjectArrayElement(env, jthreads, i, threads[i]);
}
for (i = nThreads; i < arrayLen; i++) {
(*env)->SetObjectArrayElement(env, jthreads, i, NULL);
}
(*_jvmti)->Deallocate(_jvmti, (unsigned char *) threads);
return jthreads;
}
/*
* Class : org_netbeans_lib_profiler_server_system_Threads
* Method : getThreadsStatus
* Signature : ( [ Ljava / lang / Thread ; [ I ) V
*/
JNIEXPORT void JNICALL Java_org_netbeans_lib_profiler_server_system_Threads_getThreadsStatus
(JNIEnv *env, jclass clz, jobjectArray jthreads, jintArray jstatus)
{
int nThreads, i;
jint threadStatus;
jint *status;
nThreads = (*env)->GetArrayLength(env, jthreads);
status = malloc(nThreads * sizeof (jint));
for (i = 0 ; i < nThreads; i++) {
jthread thread = (*env)->GetObjectArrayElement(env, jthreads, i);
if (thread == NULL) {
continue ;
}
(*_jvmti)->GetThreadState(_jvmti, thread, &threadStatus);
status[i] = convert_JVMTI_thread_status_to_jfluid_status(threadStatus);
}
(*env)->SetIntArrayRegion(env, jstatus, 0 , nThreads, status);
free(status);
}
/*
* Class : org_netbeans_lib_profiler_server_system_Threads
* Method : getJVMArguments
* Signature : ( ) Ljava / lang / String ;
*/
JNIEXPORT jstring JNICALL Java_org_netbeans_lib_profiler_server_system_Threads_getJVMArguments
(JNIEnv *env, jclass clz)
{
jstring ret = (*env)->NewStringUTF(env, "*NOT PROVIDED IN THIS JVM VERSION*" );
return ret;
}
/*
* Class : org_netbeans_lib_profiler_server_system_Threads
* Method : getJavaCommand
* Signature : ( ) Ljava / lang / String ;
*/
JNIEXPORT jstring JNICALL Java_org_netbeans_lib_profiler_server_system_Threads_getJavaCommand
(JNIEnv *env, jclass clz)
{
jstring ret = (*env)->NewStringUTF(env, "*NOT PROVIDED IN THIS JVM VERSION*" );
return ret;
}
Messung V0.5 in Prozent C=99 H=99 G=98
¤ Dauer der Verarbeitung: 0.4 Sekunden
¤
*© Formatika GbR, Deutschland