| // 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. |
| |
| #include "jvm_metrics.h" |
| |
| #include <util/jni-util.h> |
| |
| #include <functional> |
| |
| #include "common/config.h" |
| #include "util/metrics.h" |
| namespace doris { |
| |
| #define DEFINE_JVM_SIZE_BYTES_METRIC(name, type) \ |
| DEFINE_COUNTER_METRIC_PROTOTYPE_5ARG(name##_##type, MetricUnit::BYTES, "", name, \ |
| Labels({{"type", #type}})); |
| |
| DEFINE_JVM_SIZE_BYTES_METRIC(jvm_heap_size_bytes, max); |
| DEFINE_JVM_SIZE_BYTES_METRIC(jvm_heap_size_bytes, committed); |
| DEFINE_JVM_SIZE_BYTES_METRIC(jvm_heap_size_bytes, used); |
| |
| DEFINE_JVM_SIZE_BYTES_METRIC(jvm_non_heap_size_bytes, used); |
| DEFINE_JVM_SIZE_BYTES_METRIC(jvm_non_heap_size_bytes, committed); |
| |
| DEFINE_JVM_SIZE_BYTES_METRIC(jvm_young_size_bytes, used); |
| DEFINE_JVM_SIZE_BYTES_METRIC(jvm_young_size_bytes, peak_used); |
| DEFINE_JVM_SIZE_BYTES_METRIC(jvm_young_size_bytes, max); |
| |
| DEFINE_JVM_SIZE_BYTES_METRIC(jvm_old_size_bytes, used); |
| DEFINE_JVM_SIZE_BYTES_METRIC(jvm_old_size_bytes, peak_used); |
| DEFINE_JVM_SIZE_BYTES_METRIC(jvm_old_size_bytes, max); |
| |
| #define DEFINE_JVM_THREAD_METRIC(type) \ |
| DEFINE_COUNTER_METRIC_PROTOTYPE_5ARG(jvm_thread_##type, MetricUnit::NOUNIT, "", jvm_thread, \ |
| Labels({{"type", #type}})); |
| |
| DEFINE_JVM_THREAD_METRIC(count); |
| DEFINE_JVM_THREAD_METRIC(peak_count); |
| DEFINE_JVM_THREAD_METRIC(new_count); |
| DEFINE_JVM_THREAD_METRIC(runnable_count); |
| DEFINE_JVM_THREAD_METRIC(blocked_count); |
| DEFINE_JVM_THREAD_METRIC(waiting_count); |
| DEFINE_JVM_THREAD_METRIC(timed_waiting_count); |
| DEFINE_JVM_THREAD_METRIC(terminated_count); |
| |
| DEFINE_COUNTER_METRIC_PROTOTYPE_5ARG(jvm_gc_g1_young_generation_count, MetricUnit::NOUNIT, "", |
| jvm_gc, |
| Labels({{"name", "G1 Young generation Count"}, |
| {"type", "count"}})); |
| |
| DEFINE_COUNTER_METRIC_PROTOTYPE_5ARG(jvm_gc_g1_young_generation_time_ms, MetricUnit::MILLISECONDS, |
| "", jvm_gc, |
| Labels({{"name", "G1 Young generation Time"}, |
| {"type", "time"}})); |
| |
| DEFINE_COUNTER_METRIC_PROTOTYPE_5ARG(jvm_gc_g1_old_generation_count, MetricUnit::NOUNIT, "", jvm_gc, |
| Labels({{"name", "G1 Old generation Count"}, |
| {"type", "count"}})); |
| |
| DEFINE_COUNTER_METRIC_PROTOTYPE_5ARG(jvm_gc_g1_old_generation_time_ms, MetricUnit::MILLISECONDS, "", |
| jvm_gc, |
| Labels({{"name", "G1 Old generation Time"}, |
| {"type", "time"}})); |
| |
| const char* JvmMetrics::_s_hook_name = "jvm_metrics"; |
| |
| JvmMetrics::JvmMetrics(MetricRegistry* registry, JNIEnv* env) { |
| DCHECK(registry != nullptr); |
| _registry = registry; |
| |
| _server_entity = _registry->register_entity("server"); |
| DCHECK(_server_entity != nullptr); |
| |
| do { |
| if (!doris::config::enable_jvm_monitor) { |
| break; |
| } |
| try { |
| _jvm_stats.init(env); |
| } catch (...) { |
| LOG(WARNING) << "JVM STATS INIT FAIL"; |
| break; |
| } |
| if (!_jvm_stats.init_complete()) { |
| break; |
| } |
| _server_entity->register_hook(_s_hook_name, std::bind(&JvmMetrics::update, this)); |
| } while (false); |
| |
| INT_GAUGE_METRIC_REGISTER(_server_entity, jvm_heap_size_bytes_max); |
| INT_GAUGE_METRIC_REGISTER(_server_entity, jvm_heap_size_bytes_committed); |
| INT_GAUGE_METRIC_REGISTER(_server_entity, jvm_heap_size_bytes_used); |
| |
| INT_GAUGE_METRIC_REGISTER(_server_entity, jvm_non_heap_size_bytes_used); |
| INT_GAUGE_METRIC_REGISTER(_server_entity, jvm_non_heap_size_bytes_committed); |
| |
| INT_GAUGE_METRIC_REGISTER(_server_entity, jvm_young_size_bytes_used); |
| INT_GAUGE_METRIC_REGISTER(_server_entity, jvm_young_size_bytes_peak_used); |
| INT_GAUGE_METRIC_REGISTER(_server_entity, jvm_young_size_bytes_max); |
| |
| INT_GAUGE_METRIC_REGISTER(_server_entity, jvm_old_size_bytes_used); |
| INT_GAUGE_METRIC_REGISTER(_server_entity, jvm_old_size_bytes_peak_used); |
| INT_GAUGE_METRIC_REGISTER(_server_entity, jvm_old_size_bytes_max); |
| |
| INT_GAUGE_METRIC_REGISTER(_server_entity, jvm_thread_count); |
| INT_GAUGE_METRIC_REGISTER(_server_entity, jvm_thread_peak_count); |
| INT_GAUGE_METRIC_REGISTER(_server_entity, jvm_thread_new_count); |
| INT_GAUGE_METRIC_REGISTER(_server_entity, jvm_thread_runnable_count); |
| INT_GAUGE_METRIC_REGISTER(_server_entity, jvm_thread_blocked_count); |
| INT_GAUGE_METRIC_REGISTER(_server_entity, jvm_thread_waiting_count); |
| INT_GAUGE_METRIC_REGISTER(_server_entity, jvm_thread_timed_waiting_count); |
| INT_GAUGE_METRIC_REGISTER(_server_entity, jvm_thread_terminated_count); |
| |
| INT_GAUGE_METRIC_REGISTER(_server_entity, jvm_gc_g1_young_generation_count); |
| INT_GAUGE_METRIC_REGISTER(_server_entity, jvm_gc_g1_young_generation_time_ms); |
| INT_GAUGE_METRIC_REGISTER(_server_entity, jvm_gc_g1_old_generation_count); |
| INT_GAUGE_METRIC_REGISTER(_server_entity, jvm_gc_g1_old_generation_time_ms); |
| } |
| |
| void JvmMetrics::update() { |
| static long fail_count = 0; |
| bool have_exception = false; |
| try { |
| _jvm_stats.refresh(this); |
| } catch (...) { |
| have_exception = true; |
| LOG(WARNING) << "JVM MONITOR UPDATE FAIL!"; |
| fail_count++; |
| } |
| |
| //When 30 consecutive exceptions occur, turn off jvm information collection. |
| if (!have_exception) { |
| fail_count = 0; |
| } |
| if (fail_count >= 30) { |
| LOG(WARNING) << "JVM MONITOR CLOSE!"; |
| _jvm_stats.set_complete(false); |
| _server_entity->deregister_hook(_s_hook_name); |
| |
| jvm_heap_size_bytes_max->set_value(0); |
| jvm_heap_size_bytes_committed->set_value(0); |
| jvm_heap_size_bytes_used->set_value(0); |
| |
| jvm_non_heap_size_bytes_used->set_value(0); |
| jvm_non_heap_size_bytes_committed->set_value(0); |
| |
| jvm_young_size_bytes_used->set_value(0); |
| jvm_young_size_bytes_peak_used->set_value(0); |
| jvm_young_size_bytes_max->set_value(0); |
| |
| jvm_old_size_bytes_used->set_value(0); |
| jvm_old_size_bytes_peak_used->set_value(0); |
| jvm_old_size_bytes_max->set_value(0); |
| |
| jvm_thread_count->set_value(0); |
| jvm_thread_peak_count->set_value(0); |
| jvm_thread_new_count->set_value(0); |
| jvm_thread_runnable_count->set_value(0); |
| jvm_thread_blocked_count->set_value(0); |
| jvm_thread_waiting_count->set_value(0); |
| jvm_thread_timed_waiting_count->set_value(0); |
| jvm_thread_terminated_count->set_value(0); |
| |
| jvm_gc_g1_young_generation_count->set_value(0); |
| jvm_gc_g1_young_generation_time_ms->set_value(0); |
| jvm_gc_g1_old_generation_count->set_value(0); |
| jvm_gc_g1_old_generation_time_ms->set_value(0); |
| } |
| } |
| |
| void JvmStats::init(JNIEnv* ENV) { |
| env = ENV; |
| _managementFactoryClass = env->FindClass("java/lang/management/ManagementFactory"); |
| if (_managementFactoryClass == nullptr) { |
| LOG(WARNING) |
| << "Class java/lang/management/ManagementFactory Not Find.JVM monitoring fails."; |
| return; |
| } |
| |
| _getMemoryMXBeanMethod = env->GetStaticMethodID(_managementFactoryClass, "getMemoryMXBean", |
| "()Ljava/lang/management/MemoryMXBean;"); |
| |
| _memoryUsageClass = env->FindClass("java/lang/management/MemoryUsage"); |
| if (_memoryUsageClass == nullptr) { |
| LOG(WARNING) << "Class java/lang/management/MemoryUsage Not Find.JVM monitoring fails."; |
| return; |
| } |
| _getMemoryUsageUsedMethod = env->GetMethodID(_memoryUsageClass, "getUsed", "()J"); |
| _getMemoryUsageCommittedMethod = env->GetMethodID(_memoryUsageClass, "getCommitted", "()J"); |
| _getMemoryUsageMaxMethod = env->GetMethodID(_memoryUsageClass, "getMax", "()J"); |
| |
| _memoryMXBeanClass = env->FindClass("java/lang/management/MemoryMXBean"); |
| if (_memoryMXBeanClass == nullptr) { |
| LOG(WARNING) << "Class java/lang/management/MemoryMXBean Not Find.JVM monitoring fails."; |
| return; |
| } |
| _getHeapMemoryUsageMethod = env->GetMethodID(_memoryMXBeanClass, "getHeapMemoryUsage", |
| "()Ljava/lang/management/MemoryUsage;"); |
| _getNonHeapMemoryUsageMethod = env->GetMethodID(_memoryMXBeanClass, "getNonHeapMemoryUsage", |
| "()Ljava/lang/management/MemoryUsage;"); |
| |
| _getMemoryPoolMXBeansMethod = env->GetStaticMethodID( |
| _managementFactoryClass, "getMemoryPoolMXBeans", "()Ljava/util/List;"); |
| |
| _listClass = env->FindClass("java/util/List"); |
| if (_listClass == nullptr) { |
| LOG(WARNING) << "Class java/util/List Not Find.JVM monitoring fails."; |
| return; |
| } |
| _getListSizeMethod = env->GetMethodID(_listClass, "size", "()I"); |
| _getListUseIndexMethod = env->GetMethodID(_listClass, "get", "(I)Ljava/lang/Object;"); |
| |
| _memoryPoolMXBeanClass = env->FindClass("java/lang/management/MemoryPoolMXBean"); |
| if (_memoryPoolMXBeanClass == nullptr) { |
| LOG(WARNING) |
| << "Class java/lang/management/MemoryPoolMXBean Not Find.JVM monitoring fails."; |
| return; |
| } |
| _getMemoryPoolMXBeanUsageMethod = env->GetMethodID(_memoryPoolMXBeanClass, "getUsage", |
| "()Ljava/lang/management/MemoryUsage;"); |
| _getMemoryPollMXBeanPeakMethod = env->GetMethodID(_memoryPoolMXBeanClass, "getPeakUsage", |
| "()Ljava/lang/management/MemoryUsage;"); |
| _getMemoryPollMXBeanNameMethod = |
| env->GetMethodID(_memoryPoolMXBeanClass, "getName", "()Ljava/lang/String;"); |
| |
| _getThreadMXBeanMethod = env->GetStaticMethodID(_managementFactoryClass, "getThreadMXBean", |
| "()Ljava/lang/management/ThreadMXBean;"); |
| |
| _getGarbageCollectorMXBeansMethod = env->GetStaticMethodID( |
| _managementFactoryClass, "getGarbageCollectorMXBeans", "()Ljava/util/List;"); |
| |
| _garbageCollectorMXBeanClass = env->FindClass("java/lang/management/GarbageCollectorMXBean"); |
| if (_garbageCollectorMXBeanClass == nullptr) { |
| LOG(WARNING) << "Class java/lang/management/GarbageCollectorMXBean Not Find.JVM monitoring " |
| "fails."; |
| return; |
| } |
| _getGCNameMethod = |
| env->GetMethodID(_garbageCollectorMXBeanClass, "getName", "()Ljava/lang/String;"); |
| _getGCCollectionCountMethod = |
| env->GetMethodID(_garbageCollectorMXBeanClass, "getCollectionCount", "()J"); |
| _getGCCollectionTimeMethod = |
| env->GetMethodID(_garbageCollectorMXBeanClass, "getCollectionTime", "()J"); |
| |
| _threadMXBeanClass = env->FindClass("java/lang/management/ThreadMXBean"); |
| if (_threadMXBeanClass == nullptr) { |
| LOG(WARNING) << "Class java/lang/management/ThreadMXBean Not Find.JVM monitoring fails."; |
| return; |
| } |
| _getAllThreadIdsMethod = env->GetMethodID(_threadMXBeanClass, "getAllThreadIds", "()[J"); |
| _getThreadInfoMethod = env->GetMethodID(_threadMXBeanClass, "getThreadInfo", |
| "([JI)[Ljava/lang/management/ThreadInfo;"); |
| _getPeakThreadCountMethod = env->GetMethodID(_threadMXBeanClass, "getPeakThreadCount", "()I"); |
| |
| _threadInfoClass = env->FindClass("java/lang/management/ThreadInfo"); |
| if (_threadInfoClass == nullptr) { |
| LOG(WARNING) << "Class java/lang/management/ThreadInfo Not Find.JVM monitoring fails."; |
| return; |
| } |
| |
| _getThreadStateMethod = |
| env->GetMethodID(_threadInfoClass, "getThreadState", "()Ljava/lang/Thread$State;"); |
| |
| _threadStateClass = env->FindClass("java/lang/Thread$State"); |
| if (_threadStateClass == nullptr) { |
| LOG(WARNING) << "Class java/lang/Thread$State Not Find.JVM monitoring fails."; |
| return; |
| } |
| |
| jfieldID newThreadFieldID = |
| env->GetStaticFieldID(_threadStateClass, "NEW", "Ljava/lang/Thread$State;"); |
| jfieldID runnableThreadFieldID = |
| env->GetStaticFieldID(_threadStateClass, "RUNNABLE", "Ljava/lang/Thread$State;"); |
| jfieldID blockedThreadFieldID = |
| env->GetStaticFieldID(_threadStateClass, "BLOCKED", "Ljava/lang/Thread$State;"); |
| jfieldID waitingThreadFieldID = |
| env->GetStaticFieldID(_threadStateClass, "WAITING", "Ljava/lang/Thread$State;"); |
| jfieldID timedWaitingThreadFieldID = |
| env->GetStaticFieldID(_threadStateClass, "TIMED_WAITING", "Ljava/lang/Thread$State;"); |
| jfieldID terminatedThreadFieldID = |
| env->GetStaticFieldID(_threadStateClass, "TERMINATED", "Ljava/lang/Thread$State;"); |
| |
| _newThreadStateObj = env->GetStaticObjectField(_threadStateClass, newThreadFieldID); |
| _runnableThreadStateObj = env->GetStaticObjectField(_threadStateClass, runnableThreadFieldID); |
| _blockedThreadStateObj = env->GetStaticObjectField(_threadStateClass, blockedThreadFieldID); |
| _waitingThreadStateObj = env->GetStaticObjectField(_threadStateClass, waitingThreadFieldID); |
| _timedWaitingThreadStateObj = |
| env->GetStaticObjectField(_threadStateClass, timedWaitingThreadFieldID); |
| _terminatedThreadStateObj = |
| env->GetStaticObjectField(_threadStateClass, terminatedThreadFieldID); |
| |
| LOG(INFO) << "Start JVM monitoring."; |
| |
| _init_complete = true; |
| return; |
| } |
| |
| void JvmStats::refresh(JvmMetrics* jvm_metrics) { |
| if (!_init_complete) { |
| return; |
| } |
| |
| Status st = JniUtil::GetJNIEnv(&env); |
| if (!st.ok()) { |
| LOG(WARNING) << "JVM STATS GET JNI ENV FAIL"; |
| return; |
| } |
| |
| jobject memoryMXBeanObj = |
| env->CallStaticObjectMethod(_managementFactoryClass, _getMemoryMXBeanMethod); |
| |
| jobject heapMemoryUsageObj = env->CallObjectMethod(memoryMXBeanObj, _getHeapMemoryUsageMethod); |
| |
| jlong heapMemoryUsed = env->CallLongMethod(heapMemoryUsageObj, _getMemoryUsageUsedMethod); |
| jlong heapMemoryCommitted = |
| env->CallLongMethod(heapMemoryUsageObj, _getMemoryUsageCommittedMethod); |
| jlong heapMemoryMax = env->CallLongMethod(heapMemoryUsageObj, _getMemoryUsageMaxMethod); |
| |
| jvm_metrics->jvm_heap_size_bytes_used->set_value(heapMemoryUsed < 0 ? 0 : heapMemoryUsed); |
| jvm_metrics->jvm_heap_size_bytes_committed->set_value( |
| heapMemoryCommitted < 0 ? 0 : heapMemoryCommitted); |
| jvm_metrics->jvm_heap_size_bytes_max->set_value(heapMemoryMax < 0 ? 0 : heapMemoryMax); |
| |
| jobject nonHeapMemoryUsageObj = |
| env->CallObjectMethod(memoryMXBeanObj, _getNonHeapMemoryUsageMethod); |
| |
| jlong nonHeapMemoryCommitted = |
| env->CallLongMethod(nonHeapMemoryUsageObj, _getMemoryUsageCommittedMethod); |
| jlong nonHeapMemoryUsed = env->CallLongMethod(nonHeapMemoryUsageObj, _getMemoryUsageUsedMethod); |
| |
| jvm_metrics->jvm_non_heap_size_bytes_committed->set_value( |
| nonHeapMemoryCommitted < 0 ? 0 : nonHeapMemoryCommitted); |
| jvm_metrics->jvm_non_heap_size_bytes_used->set_value(nonHeapMemoryUsed < 0 ? 0 |
| : nonHeapMemoryUsed); |
| |
| jobject memoryPoolMXBeansList = |
| env->CallStaticObjectMethod(_managementFactoryClass, _getMemoryPoolMXBeansMethod); |
| |
| jint size = env->CallIntMethod(memoryPoolMXBeansList, _getListSizeMethod); |
| |
| for (int i = 0; i < size; ++i) { |
| jobject memoryPoolMXBean = |
| env->CallObjectMethod(memoryPoolMXBeansList, _getListUseIndexMethod, i); |
| jobject usageObject = |
| env->CallObjectMethod(memoryPoolMXBean, _getMemoryPoolMXBeanUsageMethod); |
| |
| jlong used = env->CallLongMethod(usageObject, _getMemoryUsageUsedMethod); |
| jlong max = env->CallLongMethod(usageObject, _getMemoryUsageMaxMethod); |
| |
| jobject peakUsageObject = |
| env->CallObjectMethod(memoryPoolMXBean, _getMemoryPollMXBeanPeakMethod); |
| |
| jlong peakUsed = env->CallLongMethod(peakUsageObject, _getMemoryUsageUsedMethod); |
| |
| jstring name = |
| (jstring)env->CallObjectMethod(memoryPoolMXBean, _getMemoryPollMXBeanNameMethod); |
| const char* nameStr = env->GetStringUTFChars(name, nullptr); |
| if (nameStr != nullptr) { |
| auto it = _memoryPoolName.find(nameStr); |
| if (it == _memoryPoolName.end()) { |
| continue; |
| } |
| if (it->second == memoryPoolNameEnum::YOUNG) { |
| jvm_metrics->jvm_young_size_bytes_used->set_value(used < 0 ? 0 : used); |
| jvm_metrics->jvm_young_size_bytes_peak_used->set_value(peakUsed < 0 ? 0 : peakUsed); |
| jvm_metrics->jvm_young_size_bytes_max->set_value(max < 0 ? 0 : max); |
| |
| } else if (it->second == memoryPoolNameEnum::OLD) { |
| jvm_metrics->jvm_old_size_bytes_used->set_value(used < 0 ? 0 : used); |
| jvm_metrics->jvm_old_size_bytes_peak_used->set_value(peakUsed < 0 ? 0 : peakUsed); |
| jvm_metrics->jvm_old_size_bytes_max->set_value(max < 0 ? 0 : max); |
| } |
| |
| env->ReleaseStringUTFChars(name, nameStr); |
| } |
| env->DeleteLocalRef(memoryPoolMXBean); |
| env->DeleteLocalRef(usageObject); |
| env->DeleteLocalRef(peakUsageObject); |
| } |
| |
| jobject threadMXBean = |
| env->CallStaticObjectMethod(_managementFactoryClass, _getThreadMXBeanMethod); |
| |
| jlongArray threadIds = (jlongArray)env->CallObjectMethod(threadMXBean, _getAllThreadIdsMethod); |
| jint threadCount = env->GetArrayLength(threadIds); |
| |
| jobjectArray threadInfos = |
| (jobjectArray)env->CallObjectMethod(threadMXBean, _getThreadInfoMethod, threadIds, 0); |
| |
| int threadsNew = 0, threadsRunnable = 0, threadsBlocked = 0, threadsWaiting = 0, |
| threadsTimedWaiting = 0, threadsTerminated = 0; |
| jint peakThreadCount = env->CallIntMethod(threadMXBean, _getPeakThreadCountMethod); |
| |
| jvm_metrics->jvm_thread_peak_count->set_value(peakThreadCount < 0 ? 0 : peakThreadCount); |
| jvm_metrics->jvm_thread_count->set_value(threadCount < 0 ? 0 : threadCount); |
| |
| for (int i = 0; i < threadCount; i++) { |
| jobject threadInfo = env->GetObjectArrayElement(threadInfos, i); |
| if (threadInfo == nullptr) { |
| continue; |
| } |
| jobject threadState = env->CallObjectMethod(threadInfo, _getThreadStateMethod); |
| |
| if (env->IsSameObject(threadState, _newThreadStateObj)) { |
| threadsNew++; |
| } else if (env->IsSameObject(threadState, _runnableThreadStateObj)) { |
| threadsRunnable++; |
| } else if (env->IsSameObject(threadState, _blockedThreadStateObj)) { |
| threadsBlocked++; |
| } else if (env->IsSameObject(threadState, _waitingThreadStateObj)) { |
| threadsWaiting++; |
| } else if (env->IsSameObject(threadState, _timedWaitingThreadStateObj)) { |
| threadsTimedWaiting++; |
| } else if (env->IsSameObject(threadState, _terminatedThreadStateObj)) { |
| threadsTerminated++; |
| } |
| env->DeleteLocalRef(threadInfo); |
| env->DeleteLocalRef(threadState); |
| } |
| |
| jvm_metrics->jvm_thread_new_count->set_value(threadsNew < 0 ? 0 : threadsNew); |
| jvm_metrics->jvm_thread_runnable_count->set_value(threadsRunnable < 0 ? 0 : threadsRunnable); |
| jvm_metrics->jvm_thread_blocked_count->set_value(threadsBlocked < 0 ? 0 : threadsBlocked); |
| jvm_metrics->jvm_thread_waiting_count->set_value(threadsWaiting < 0 ? 0 : threadsWaiting); |
| jvm_metrics->jvm_thread_timed_waiting_count->set_value( |
| threadsTimedWaiting < 0 ? 0 : threadsTimedWaiting); |
| jvm_metrics->jvm_thread_terminated_count->set_value(threadsTerminated < 0 ? 0 |
| : threadsTerminated); |
| |
| jobject gcMXBeansList = |
| env->CallStaticObjectMethod(_managementFactoryClass, _getGarbageCollectorMXBeansMethod); |
| |
| jint numCollectors = env->CallIntMethod(gcMXBeansList, _getListSizeMethod); |
| |
| for (int i = 0; i < numCollectors; i++) { |
| jobject gcMXBean = env->CallObjectMethod(gcMXBeansList, _getListUseIndexMethod, i); |
| |
| jstring gcName = (jstring)env->CallObjectMethod(gcMXBean, _getGCNameMethod); |
| jlong gcCollectionCount = env->CallLongMethod(gcMXBean, _getGCCollectionCountMethod); |
| jlong gcCollectionTime = env->CallLongMethod(gcMXBean, _getGCCollectionTimeMethod); |
| const char* gcNameStr = env->GetStringUTFChars(gcName, NULL); |
| if (gcNameStr != nullptr) { |
| if (strcmp(gcNameStr, "G1 Young Generation") == 0) { |
| jvm_metrics->jvm_gc_g1_young_generation_count->set_value(gcCollectionCount); |
| jvm_metrics->jvm_gc_g1_young_generation_time_ms->set_value(gcCollectionTime); |
| |
| } else { |
| jvm_metrics->jvm_gc_g1_old_generation_count->set_value(gcCollectionCount); |
| jvm_metrics->jvm_gc_g1_old_generation_time_ms->set_value(gcCollectionTime); |
| } |
| |
| env->ReleaseStringUTFChars(gcName, gcNameStr); |
| } |
| env->DeleteLocalRef(gcMXBean); |
| } |
| env->DeleteLocalRef(memoryMXBeanObj); |
| env->DeleteLocalRef(heapMemoryUsageObj); |
| env->DeleteLocalRef(nonHeapMemoryUsageObj); |
| env->DeleteLocalRef(memoryPoolMXBeansList); |
| env->DeleteLocalRef(threadMXBean); |
| env->DeleteLocalRef(gcMXBeansList); |
| } |
| JvmStats::~JvmStats() { |
| if (!_init_complete) { |
| return; |
| } |
| try { |
| env->DeleteLocalRef(_newThreadStateObj); |
| env->DeleteLocalRef(_runnableThreadStateObj); |
| env->DeleteLocalRef(_blockedThreadStateObj); |
| env->DeleteLocalRef(_waitingThreadStateObj); |
| env->DeleteLocalRef(_timedWaitingThreadStateObj); |
| env->DeleteLocalRef(_terminatedThreadStateObj); |
| |
| } catch (...) { |
| // When be is killed, DeleteLocalRef may fail. |
| // In order to exit more gracefully, we catch the exception here. |
| } |
| } |
| |
| } // namespace doris |