--- /dev/null 2016-10-25 08:46:44.038854975 +0200 +++ new/src/share/vm/evtrace/traceJavaBridge.cpp 2016-10-25 10:40:14.123780799 +0200 @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved. + * + * This file is part of the Lock Contention Tracing Subsystem for the HotSpot + * Virtual Machine, which is developed at Christian Doppler Laboratory on + * Monitoring and Evolution of Very-Large-Scale Software Systems. Please + * contact us at if you need additional information + * or have any questions. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work. If not, see . + * + */ + +#include "evtrace/traceJavaBridge.hpp" + +#include "evtrace/traceBuffer.hpp" +#include "evtrace/traceBufferQueue.hpp" +#include "evtrace/traceEvents.hpp" +#include "evtrace/traceWriter.hpp" +#include "evtrace/traceReaderThread.hpp" + +#include "prims/jni.h" +#include "runtime/interfaceSupport.hpp" +#include "runtime/javaCalls.hpp" + +#define TEVT_ENTRY(result_type, header) \ + JVM_ENTRY(result_type, header) + +#define TEVT_END JVM_END + +TEVT_ENTRY(jobject, TEvT_DequeueBuffer(JNIEnv *env, jobject self, jlong queue_handle, const jboolean should_block)) + TraceBufferQueue *queue = (TraceBufferQueue *) queue_handle; + + TraceBuffer *buffer; + + if (thread->is_TraceReader_thread()) { + // we do this to avoid interrupting the thread at a bad time + ((TraceReaderThread *) thread)->set_is_polling_queue(true); + } + jlong delay = 4; + for (;;) { + buffer = queue->try_dequeue(); + if (buffer != NULL || !should_block || !TraceManager::is_initialized()) { + break; + } + + os::sleep(thread, delay, true); + if (delay <= 64) { + delay = 2 * delay; + } + } + if (thread->is_TraceReader_thread()) { + ((TraceReaderThread *) thread)->set_is_polling_queue(false); + } + + jobject bufobj = NULL; + if (buffer != NULL) { + ThreadToNativeFromVM ttn(thread); + + jlong handle = (jlong) ((uintptr_t) buffer); // sign extension paranoia + size_t length = buffer->filled_size(); + jobject bytebuf = env->NewDirectByteBuffer(buffer->data, length); + jclass clazz = env->FindClass("sun/evtracing/TraceBuffer"); + jmethodID method = env->GetMethodID(clazz, "", "(JLjava/nio/ByteBuffer;J)V"); + assert(method != NULL, "must be successful"); + bufobj = env->NewObject(clazz, method, handle, bytebuf, buffer->owner_id); + assert(bufobj != NULL, "must succeed"); + } + return bufobj; +TEVT_END + +TEVT_ENTRY(void, TEvT_EnqueueBuffer(JNIEnv *env, jobject self, jlong queue_handle, jlong buffer_handle)) + TraceBufferQueue *queue = (TraceBufferQueue *) queue_handle; + queue->enqueue((TraceBuffer *) buffer_handle); +TEVT_END + +TEVT_ENTRY(void, TEvT_ResetAndEnqueueBuffer(JNIEnv *env, jobject self, jlong queue_handle, jlong buffer_handle)) + TraceBuffer *buffer = (TraceBuffer *) buffer_handle; + buffer->reset(); + TraceBufferQueue *queue = (TraceBufferQueue *) queue_handle; + queue->enqueue((TraceBuffer *) buffer_handle); +TEVT_END + +TEVT_ENTRY(void, TEvT_FreeBuffer(JNIEnv *env, jobject self, jlong buffer_handle)) + TraceBuffer *buffer = (TraceBuffer *) buffer_handle; + TraceManager::free_buffer(buffer); +TEVT_END + +TEVT_ENTRY(jlong, TEvT_QueueCount(JNIEnv *env, jobject self, jlong queue_handle)) + TraceBufferQueue *queue = (TraceBufferQueue *) queue_handle; + return (jlong) queue->count();TEVT_END + +TEVT_ENTRY(void, TEvT_WriteGroupEvent(JNIEnv *env, jobject self, jlong park_global_seq_begin_ref, jobject source)) + TraceEvents::write_group(thread, park_global_seq_begin_ref, instanceOop(JNIHandles::resolve_non_null(source))); +TEVT_END + +TEVT_ENTRY(jstring, TEvT_GetConfiguration(JNIEnv *env, jobject self)) + jstring config = NULL; + if (EventTracingConfiguration != NULL && EventTracingConfiguration[0] != '\0') { + ThreadToNativeFromVM ttn(thread); + config = env->NewStringUTF(EventTracingConfiguration); + } + return config; +TEVT_END + +TEVT_ENTRY(void, TEvT_PutNativeStatistics(JNIEnv *env, jobject self, jobject map)) + JavaTraceStatistics jts(env, thread, instanceHandle(instanceOop(JNIHandles::resolve_non_null(map))), CHECK); + TraceManager::write_stats(&jts); +TEVT_END + +JavaTraceStatistics::JavaTraceStatistics(JNIEnv* env, JavaThread* thread, instanceHandle map, TRAPS) +: _env(env), + THREAD(THREAD), + _hashmap_obj(map) +{ +} + +void JavaTraceStatistics::add_entry(const char* name, jdouble value) { + assert(name != NULL, "must not be NULL"); + + // assume utf8 string to save native transition required by java_lang_String::create_from_platform_dependent_str + Handle name_str = java_lang_String::create_from_str(name, CHECK); + oop value_oop = java_lang_boxing_object::create(T_DOUBLE, (jvalue*) &value, CHECK); + Handle value_handle(THREAD, value_oop); + + JavaValue result(T_OBJECT); + JavaCalls::call_virtual(&result, + _hashmap_obj, + _hashmap_obj->klass(), + vmSymbols::put_name(), + vmSymbols::object_object_object_signature(), + name_str, + value_handle, + CHECK); +} + +TEVT_ENTRY(void, TEvT_ResetNativeStatistics(JNIEnv *env, jobject self)) + TraceManager::reset_stats(); +TEVT_END + +TEVT_ENTRY(void, TEvT_ResetNativeMetadata(JNIEnv *env, jobject self)) + TraceManager::reset_metadata(); +TEVT_END + +TEVT_ENTRY(void, TEvT_ReclaimBuffers(JNIEnv *env, jobject self, jboolean wait_until_processed)) + TraceManager::reclaim_buffers_in_safepoint(wait_until_processed); +TEVT_END + +#define CC (char*) /*cast a literal from (const char*)*/ +#define FN_PTR(f) CAST_FROM_FN_PTR(void*, &f) + +static JNINativeMethod tevtmethods[] = { + {CC"dequeueBuffer", CC"(JZ)Lsun/evtracing/TraceBuffer;", FN_PTR(TEvT_DequeueBuffer)}, + {CC"enqueueBuffer", CC"(JJ)V", FN_PTR(TEvT_EnqueueBuffer)}, + {CC"resetAndEnqueueBuffer", CC"(JJ)V", FN_PTR(TEvT_ResetAndEnqueueBuffer)}, + {CC"freeBuffer", CC"(J)V", FN_PTR(TEvT_FreeBuffer)}, + {CC"queueCount", CC"(J)J", FN_PTR(TEvT_QueueCount) }, + {CC"writeGroupEvent", CC"(JLjava/lang/Object;)V", FN_PTR(TEvT_WriteGroupEvent)}, + {CC"getConfiguration", CC"()Ljava/lang/String;", FN_PTR(TEvT_GetConfiguration)}, + {CC"putNativeStatistics", CC"(Ljava/util/Map;)V", FN_PTR(TEvT_PutNativeStatistics)}, + {CC"resetNativeStatistics", CC"()V", FN_PTR(TEvT_ResetNativeStatistics)}, + {CC"resetNativeMetadata", CC"()V", FN_PTR(TEvT_ResetNativeMetadata)}, + {CC"reclaimBuffers", CC"(Z)V", FN_PTR(TEvT_ReclaimBuffers)}, +}; + +JVM_ENTRY(jboolean, JVM_RegisterEventTracingMethods(JNIEnv* env, jclass tevtclass)) + if (EnableEventTracing) { + ThreadToNativeFromVM ttnfv(thread); + int ok = env->RegisterNatives(tevtclass, tevtmethods, sizeof(tevtmethods) / sizeof(JNINativeMethod)); + guarantee(ok == 0, "register event tracing natives"); + } + return EnableEventTracing; +JVM_END