Path: blob/master/src/hotspot/share/jfr/leakprofiler/checkpoint/objectSampleDescription.cpp
41155 views
/*1* Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324#include "precompiled.hpp"25#include "jvm_io.h"26#include "classfile/javaClasses.inline.hpp"27#include "classfile/symbolTable.hpp"28#include "classfile/vmClasses.hpp"29#include "classfile/vmSymbols.hpp"30#include "jfr/leakprofiler/checkpoint/objectSampleDescription.hpp"31#include "jfr/recorder/checkpoint/jfrCheckpointWriter.hpp"32#include "oops/oop.inline.hpp"33#include "runtime/fieldDescriptor.inline.hpp"34#include "runtime/thread.hpp"35#include "utilities/ostream.hpp"3637static Symbol* symbol_size = NULL;3839ObjectDescriptionBuilder::ObjectDescriptionBuilder() {40reset();41}4243void ObjectDescriptionBuilder::write_int(jint value) {44char buf[20];45jio_snprintf(buf, sizeof(buf), "%d", value);46write_text(buf);47}4849void ObjectDescriptionBuilder::write_text(const char* text) {50if (_index == sizeof(_buffer) - 2) {51return;52}53while (*text != '\0' && _index < sizeof(_buffer) - 2) {54_buffer[_index] = *text;55_index++;56text++;57}58assert(_index < sizeof(_buffer) - 1, "index should not exceed buffer size");59// add ellipsis if we reached end60if (_index == sizeof(_buffer) - 2) {61_buffer[_index-3] = '.';62_buffer[_index-2] = '.';63_buffer[_index-1] = '.';64}65// terminate string66_buffer[_index] = '\0';67}6869void ObjectDescriptionBuilder::reset() {70_index = 0;71_buffer[0] = '\0';72}7374void ObjectDescriptionBuilder::print_description(outputStream* out) {75out->print("%s", (const char*)_buffer);76}7778const char* ObjectDescriptionBuilder::description() {79if (_buffer[0] == '\0') {80return NULL;81}82const size_t len = strlen(_buffer);83char* copy = NEW_RESOURCE_ARRAY(char, len + 1);84assert(copy != NULL, "invariant");85strncpy(copy, _buffer, len + 1);86return copy;87}8889ObjectSampleDescription::ObjectSampleDescription(oop object) :90_object(object) {91}9293void ObjectSampleDescription::ensure_initialized() {94if (symbol_size == NULL) {95symbol_size = SymbolTable::new_permanent_symbol("size");96}97}9899void ObjectSampleDescription::print_description(outputStream* out) {100write_object_to_buffer();101_description.print_description(out);102}103104const char* ObjectSampleDescription::description() {105write_object_to_buffer();106return _description.description();107}108109void ObjectSampleDescription::write_text(const char* text) {110_description.write_text(text);111}112113void ObjectSampleDescription::write_int(jint value) {114_description.write_int(value);115}116117void ObjectSampleDescription::write_object_to_buffer() {118ensure_initialized();119_description.reset();120write_object_details();121}122123void ObjectSampleDescription::write_object_details() {124Klass* klass = _object->klass();125Symbol* class_name = klass->name();126jint size;127128if (_object->is_a(vmClasses::Class_klass())) {129write_class_name();130return;131}132133if (_object->is_a(vmClasses::Thread_klass())) {134write_thread_name();135return;136}137138if (_object->is_a(vmClasses::ThreadGroup_klass())) {139write_thread_group_name();140return;141}142143if (read_int_size(&size)) {144write_size(size);145return;146}147}148149void ObjectSampleDescription::write_class_name() {150assert(_object->is_a(vmClasses::Class_klass()), "invariant");151const Klass* const k = java_lang_Class::as_Klass(_object);152if (k == NULL) {153// might represent a primitive154const Klass* const ak = java_lang_Class::array_klass_acquire(_object);155// If ak is NULL, this is most likely a mirror associated with a156// jvmti redefine/retransform scratch klass. We can't get any additional157// information from it.158if (ak != NULL) {159write_text(type2name(java_lang_Class::primitive_type(_object)));160}161return;162}163164if (k->is_instance_klass()) {165const InstanceKlass* ik = InstanceKlass::cast(k);166if (ik->is_hidden()) {167return;168}169const Symbol* name = ik->name();170if (name != NULL) {171write_text("Class Name: ");172write_text(name->as_klass_external_name());173}174}175}176177void ObjectSampleDescription::write_thread_group_name() {178assert(_object->is_a(vmClasses::ThreadGroup_klass()), "invariant");179const char* tg_name = java_lang_ThreadGroup::name(_object);180if (tg_name != NULL) {181write_text("Thread Group: ");182write_text(tg_name);183}184}185186void ObjectSampleDescription::write_thread_name() {187assert(_object->is_a(vmClasses::Thread_klass()), "invariant");188oop name = java_lang_Thread::name(_object);189if (name != NULL) {190char* p = java_lang_String::as_utf8_string(name);191if (p != NULL) {192write_text("Thread Name: ");193write_text(p);194}195}196}197198void ObjectSampleDescription::write_size(jint size) {199if (size >= 0) {200write_text("Size: ");201write_int(size);202}203}204205bool ObjectSampleDescription::read_int_size(jint* result_size) {206fieldDescriptor fd;207Klass* klass = _object->klass();208if (klass->is_instance_klass()) {209InstanceKlass* ik = InstanceKlass::cast(klass);210if (ik->find_field(symbol_size, vmSymbols::int_signature(), false, &fd) != NULL) {211jint size = _object->int_field(fd.offset());212*result_size = size;213return true;214}215}216return false;217}218219220