8232759: Remove GC.class_stats

Make the GC.class_stats option obsolete

Reviewed-by: dholmes, iklam
This commit is contained in:
Coleen Phillimore 2020-01-09 17:38:41 -05:00
parent 943b87ddde
commit 016b0f0caa
28 changed files with 90 additions and 823 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -100,7 +100,7 @@ void GCTracer::report_object_count_after_gc(BoolObjectClosure* is_alive_cl) {
KlassInfoTable cit(false);
if (!cit.allocation_failed()) {
HeapInspection hi(false, false, false, NULL);
HeapInspection hi;
hi.populate_table(&cit, is_alive_cl);
ObjectCountEventSenderClosure event_sender(cit.size_of_instances_in_words(), Ticks::now());
cit.iterate(&event_sender);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -151,8 +151,7 @@ void VM_GC_HeapInspection::doit() {
log_warning(gc)("GC locker is held; pre-dump GC was skipped");
}
}
HeapInspection inspect(_csv_format, _print_help, _print_class_stats,
_columns);
HeapInspection inspect;
inspect.heap_inspection(_out);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -125,32 +125,17 @@ class VM_GC_HeapInspection: public VM_GC_Operation {
private:
outputStream* _out;
bool _full_gc;
bool _csv_format; // "comma separated values" format for spreadsheet.
bool _print_help;
bool _print_class_stats;
const char* _columns;
public:
VM_GC_HeapInspection(outputStream* out, bool request_full_gc) :
VM_GC_Operation(0 /* total collections, dummy, ignored */,
GCCause::_heap_inspection /* GC Cause */,
0 /* total full collections, dummy, ignored */,
request_full_gc) {
_out = out;
_full_gc = request_full_gc;
_csv_format = false;
_print_help = false;
_print_class_stats = false;
_columns = NULL;
}
request_full_gc), _out(out), _full_gc(request_full_gc) {}
~VM_GC_HeapInspection() {}
virtual VMOp_Type type() const { return VMOp_GC_HeapInspection; }
virtual bool skip_operation() const;
virtual void doit();
void set_csv_format(bool value) {_csv_format = value;}
void set_print_help(bool value) {_print_help = value;}
void set_print_class_stats(bool value) {_print_class_stats = value;}
void set_columns(const char* value) {_columns = value;}
protected:
bool collect();
};

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -40,14 +40,6 @@
// HeapInspection
int KlassSizeStats::count(oop x) {
return (HeapWordSize * (((x) != NULL) ? (x)->size() : 0));
}
int KlassSizeStats::count_array(objArrayOop x) {
return (HeapWordSize * (((x) != NULL) ? (x)->size() : 0));
}
inline KlassInfoEntry::~KlassInfoEntry() {
if (_subclasses != NULL) {
delete _subclasses;
@ -277,67 +269,6 @@ void KlassInfoHisto::print_elements(outputStream* st) const {
total, totalw * HeapWordSize);
}
#define MAKE_COL_NAME(field, name, help) #name,
#define MAKE_COL_HELP(field, name, help) help,
static const char *name_table[] = {
HEAP_INSPECTION_COLUMNS_DO(MAKE_COL_NAME)
};
static const char *help_table[] = {
HEAP_INSPECTION_COLUMNS_DO(MAKE_COL_HELP)
};
bool KlassInfoHisto::is_selected(const char *col_name) {
if (_selected_columns == NULL) {
return true;
}
if (strcmp(_selected_columns, col_name) == 0) {
return true;
}
const char *start = strstr(_selected_columns, col_name);
if (start == NULL) {
return false;
}
// The following must be true, because _selected_columns != col_name
if (start > _selected_columns && start[-1] != ',') {
return false;
}
char x = start[strlen(col_name)];
if (x != ',' && x != '\0') {
return false;
}
return true;
}
void KlassInfoHisto::print_title(outputStream* st, bool csv_format,
bool selected[], int width_table[],
const char *name_table[]) {
if (csv_format) {
st->print("Index,Super");
for (int c=0; c<KlassSizeStats::_num_columns; c++) {
if (selected[c]) {st->print(",%s", name_table[c]);}
}
st->print(",ClassName");
} else {
st->print("Index Super");
for (int c = 0; c < KlassSizeStats::_num_columns; c++) {
if (selected[c]) {
st->print("%*s", width_table[c], name_table[c]);
}
}
st->print(" ClassName");
}
if (is_selected("ClassLoader")) {
st->print(",ClassLoader");
}
st->cr();
}
class HierarchyClosure : public KlassInfoClosure {
private:
GrowableArray<KlassInfoEntry*> *_elements;
@ -528,155 +459,10 @@ void KlassHierarchy::print_class(outputStream* st, KlassInfoEntry* cie, bool pri
}
}
void KlassInfoHisto::print_class_stats(outputStream* st,
bool csv_format, const char *columns) {
ResourceMark rm;
KlassSizeStats sz, sz_sum;
int i;
julong *col_table = (julong*)(&sz);
julong *colsum_table = (julong*)(&sz_sum);
int width_table[KlassSizeStats::_num_columns];
bool selected[KlassSizeStats::_num_columns];
_selected_columns = columns;
memset(&sz_sum, 0, sizeof(sz_sum));
for (int c=0; c<KlassSizeStats::_num_columns; c++) {
selected[c] = is_selected(name_table[c]);
}
for(i=0; i < elements()->length(); i++) {
elements()->at(i)->set_index(i+1);
}
// First iteration is for accumulating stats totals in colsum_table[].
// Second iteration is for printing stats for each class.
for (int pass=1; pass<=2; pass++) {
if (pass == 2) {
print_title(st, csv_format, selected, width_table, name_table);
}
for(i=0; i < elements()->length(); i++) {
KlassInfoEntry* e = (KlassInfoEntry*)elements()->at(i);
const Klass* k = e->klass();
// Get the stats for this class.
memset(&sz, 0, sizeof(sz));
sz._inst_count = e->count();
sz._inst_bytes = HeapWordSize * e->words();
k->collect_statistics(&sz);
sz._total_bytes = sz._ro_bytes + sz._rw_bytes;
if (pass == 1) {
// Add the stats for this class to the overall totals.
for (int c=0; c<KlassSizeStats::_num_columns; c++) {
colsum_table[c] += col_table[c];
}
} else {
int super_index = -1;
// Print the stats for this class.
if (k->is_instance_klass()) {
Klass* super = k->super();
if (super) {
KlassInfoEntry* super_e = _cit->lookup(super);
if (super_e) {
super_index = super_e->index();
}
}
}
if (csv_format) {
st->print("%ld,%d", e->index(), super_index);
for (int c=0; c<KlassSizeStats::_num_columns; c++) {
if (selected[c]) {st->print("," JULONG_FORMAT, col_table[c]);}
}
st->print(",%s",e->name());
} else {
st->print("%5ld %5d", e->index(), super_index);
for (int c=0; c<KlassSizeStats::_num_columns; c++) {
if (selected[c]) {print_julong(st, width_table[c], col_table[c]);}
}
st->print(" %s", e->name());
}
if (is_selected("ClassLoader")) {
ClassLoaderData* loader_data = k->class_loader_data();
st->print(",");
loader_data->print_value_on(st);
}
st->cr();
}
}
if (pass == 1) {
// Calculate the minimum width needed for the column by accounting for the
// column header width and the width of the largest value in the column.
for (int c=0; c<KlassSizeStats::_num_columns; c++) {
width_table[c] = col_width(colsum_table[c], name_table[c]);
}
}
}
sz_sum._inst_size = 0;
// Print the column totals.
if (csv_format) {
st->print(",");
for (int c=0; c<KlassSizeStats::_num_columns; c++) {
if (selected[c]) {st->print("," JULONG_FORMAT, colsum_table[c]);}
}
} else {
st->print(" ");
for (int c=0; c<KlassSizeStats::_num_columns; c++) {
if (selected[c]) {print_julong(st, width_table[c], colsum_table[c]);}
}
st->print(" Total");
if (sz_sum._total_bytes > 0) {
st->cr();
st->print(" ");
for (int c=0; c<KlassSizeStats::_num_columns; c++) {
if (selected[c]) {
switch (c) {
case KlassSizeStats::_index_inst_size:
case KlassSizeStats::_index_inst_count:
case KlassSizeStats::_index_method_count:
st->print("%*s", width_table[c], "-");
break;
default:
{
double perc = (double)(100) * (double)(colsum_table[c]) / (double)sz_sum._total_bytes;
st->print("%*.1f%%", width_table[c]-1, perc);
}
}
}
}
}
}
st->cr();
if (!csv_format) {
print_title(st, csv_format, selected, width_table, name_table);
}
}
julong KlassInfoHisto::annotations_bytes(Array<AnnotationArray*>* p) const {
julong bytes = 0;
if (p != NULL) {
for (int i = 0; i < p->length(); i++) {
bytes += count_bytes_array(p->at(i));
}
bytes += count_bytes_array(p);
}
return bytes;
}
void KlassInfoHisto::print_histo_on(outputStream* st, bool print_stats,
bool csv_format, const char *columns) {
if (print_stats) {
print_class_stats(st, csv_format, columns);
} else {
st->print_cr(" num #instances #bytes class name (module)");
st->print_cr("-------------------------------------------------------");
print_elements(st);
}
void KlassInfoHisto::print_histo_on(outputStream* st) {
st->print_cr(" num #instances #bytes class name (module)");
st->print_cr("-------------------------------------------------------");
print_elements(st);
}
class HistoClosure : public KlassInfoClosure {
@ -726,25 +512,7 @@ size_t HeapInspection::populate_table(KlassInfoTable* cit, BoolObjectClosure *fi
void HeapInspection::heap_inspection(outputStream* st) {
ResourceMark rm;
if (_print_help) {
for (int c=0; c<KlassSizeStats::_num_columns; c++) {
st->print("%s:\n\t", name_table[c]);
const int max_col = 60;
int col = 0;
for (const char *p = help_table[c]; *p; p++,col++) {
if (col >= max_col && *p == ' ') {
st->print("\n\t");
col = 0;
} else {
st->print("%c", *p);
}
}
st->print_cr(".\n");
}
return;
}
KlassInfoTable cit(_print_class_stats);
KlassInfoTable cit(true);
if (!cit.allocation_failed()) {
// populate table with object allocation info
size_t missed_count = populate_table(&cit);
@ -761,7 +529,7 @@ void HeapInspection::heap_inspection(outputStream* st) {
cit.iterate(&hc);
histo.sort();
histo.print_histo_on(st, _print_class_stats, _csv_format, _columns);
histo.print_histo_on(st);
} else {
st->print_cr("ERROR: Ran out of C-heap; histogram not generated");
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -47,141 +47,6 @@
// to KlassInfoEntry's and is used to sort
// the entries.
#define HEAP_INSPECTION_COLUMNS_DO(f) \
f(inst_size, InstSize, \
"Size of each object instance of the Java class") \
f(inst_count, InstCount, \
"Number of object instances of the Java class") \
f(inst_bytes, InstBytes, \
"This is usually (InstSize * InstNum). The only exception is " \
"java.lang.Class, whose InstBytes also includes the slots " \
"used to store static fields. InstBytes is not counted in " \
"ROAll, RWAll or Total") \
f(mirror_bytes, Mirror, \
"Size of the Klass::java_mirror() object") \
f(klass_bytes, KlassBytes, \
"Size of the InstanceKlass or ArrayKlass for this class. " \
"Note that this includes VTab, ITab, OopMap") \
f(secondary_supers_bytes, K_secondary_supers, \
"Number of bytes used by the Klass::secondary_supers() array") \
f(vtab_bytes, VTab, \
"Size of the embedded vtable in InstanceKlass") \
f(itab_bytes, ITab, \
"Size of the embedded itable in InstanceKlass") \
f(nonstatic_oopmap_bytes, OopMap, \
"Size of the embedded nonstatic_oop_map in InstanceKlass") \
f(methods_array_bytes, IK_methods, \
"Number of bytes used by the InstanceKlass::methods() array") \
f(method_ordering_bytes, IK_method_ordering, \
"Number of bytes used by the InstanceKlass::method_ordering() array") \
f(default_methods_array_bytes, IK_default_methods, \
"Number of bytes used by the InstanceKlass::default_methods() array") \
f(default_vtable_indices_bytes, IK_default_vtable_indices, \
"Number of bytes used by the InstanceKlass::default_vtable_indices() array") \
f(local_interfaces_bytes, IK_local_interfaces, \
"Number of bytes used by the InstanceKlass::local_interfaces() array") \
f(transitive_interfaces_bytes, IK_transitive_interfaces, \
"Number of bytes used by the InstanceKlass::transitive_interfaces() array") \
f(fields_bytes, IK_fields, \
"Number of bytes used by the InstanceKlass::fields() array") \
f(inner_classes_bytes, IK_inner_classes, \
"Number of bytes used by the InstanceKlass::inner_classes() array") \
f(nest_members_bytes, IK_nest_members, \
"Number of bytes used by the InstanceKlass::nest_members() array") \
f(record_components_bytes, IK_record_components, \
"Number of bytes used by the InstanceKlass::record_components() array") \
f(signers_bytes, IK_signers, \
"Number of bytes used by the InstanceKlass::singers() array") \
f(class_annotations_bytes, class_annotations, \
"Size of class annotations") \
f(class_type_annotations_bytes, class_type_annotations, \
"Size of class type annotations") \
f(fields_annotations_bytes, fields_annotations, \
"Size of field annotations") \
f(fields_type_annotations_bytes, fields_type_annotations, \
"Size of field type annotations") \
f(methods_annotations_bytes, methods_annotations, \
"Size of method annotations") \
f(methods_parameter_annotations_bytes, methods_parameter_annotations, \
"Size of method parameter annotations") \
f(methods_type_annotations_bytes, methods_type_annotations, \
"Size of methods type annotations") \
f(methods_default_annotations_bytes, methods_default_annotations, \
"Size of methods default annotations") \
f(annotations_bytes, annotations, \
"Size of all annotations") \
f(cp_bytes, Cp, \
"Size of InstanceKlass::constants()") \
f(cp_tags_bytes, CpTags, \
"Size of InstanceKlass::constants()->tags()") \
f(cp_cache_bytes, CpCache, \
"Size of InstanceKlass::constants()->cache()") \
f(cp_operands_bytes, CpOperands, \
"Size of InstanceKlass::constants()->operands()") \
f(cp_refmap_bytes, CpRefMap, \
"Size of InstanceKlass::constants()->reference_map()") \
f(cp_all_bytes, CpAll, \
"Sum of Cp + CpTags + CpCache + CpOperands + CpRefMap") \
f(method_count, MethodCount, \
"Number of methods in this class") \
f(method_bytes, MethodBytes, \
"Size of the Method object") \
f(const_method_bytes, ConstMethod, \
"Size of the ConstMethod object") \
f(method_data_bytes, MethodData, \
"Size of the MethodData object") \
f(stackmap_bytes, StackMap, \
"Size of the stackmap_data") \
f(bytecode_bytes, Bytecodes, \
"Of the MethodBytes column, how much are the space taken up by bytecodes") \
f(method_all_bytes, MethodAll, \
"Sum of MethodBytes + Constmethod + Stackmap + Methoddata") \
f(ro_bytes, ROAll, \
"Size of all class meta data that could (potentially) be placed " \
"in read-only memory. (This could change with CDS design)") \
f(rw_bytes, RWAll, \
"Size of all class meta data that must be placed in read/write " \
"memory. (This could change with CDS design) ") \
f(total_bytes, Total, \
"ROAll + RWAll. Note that this does NOT include InstBytes.")
// Size statistics for a Klass - filled in by Klass::collect_statistics()
class KlassSizeStats {
public:
#define COUNT_KLASS_SIZE_STATS_FIELD(field, name, help) _index_ ## field,
#define DECLARE_KLASS_SIZE_STATS_FIELD(field, name, help) julong _ ## field;
enum {
HEAP_INSPECTION_COLUMNS_DO(COUNT_KLASS_SIZE_STATS_FIELD)
_num_columns
};
HEAP_INSPECTION_COLUMNS_DO(DECLARE_KLASS_SIZE_STATS_FIELD)
static int count(oop x);
static int count_array(objArrayOop x);
template <class T> static int count(T* x) {
return (HeapWordSize * ((x) ? (x)->size() : 0));
}
template <class T> static int count_array(T* x) {
if (x == NULL) {
return 0;
}
if (x->length() == 0) {
// This is a shared array, e.g., Universe::the_empty_int_array(). Don't
// count it to avoid double-counting.
return 0;
}
return HeapWordSize * x->size();
}
};
class KlassInfoEntry: public CHeapObj<mtInternal> {
private:
KlassInfoEntry* _next;
@ -281,13 +146,7 @@ class KlassInfoHisto : public StackObj {
GrowableArray<KlassInfoEntry*>* elements() const { return _elements; }
static int sort_helper(KlassInfoEntry** e1, KlassInfoEntry** e2);
void print_elements(outputStream* st) const;
void print_class_stats(outputStream* st, bool csv_format, const char *columns);
julong annotations_bytes(Array<AnnotationArray*>* p) const;
const char *_selected_columns;
bool is_selected(const char *col_name);
void print_title(outputStream* st, bool csv_format,
bool selected_columns_table[], int width_table[],
const char *name_table[]);
template <class T> static int count_bytes(T* x) {
return (HeapWordSize * ((x) ? (x)->size() : 0));
@ -339,7 +198,7 @@ class KlassInfoHisto : public StackObj {
KlassInfoHisto(KlassInfoTable* cit);
~KlassInfoHisto();
void add(KlassInfoEntry* cie);
void print_histo_on(outputStream* st, bool print_class_stats, bool csv_format, const char *columns);
void print_histo_on(outputStream* st);
void sort();
};
@ -351,15 +210,7 @@ class KlassInfoTable;
class KlassInfoClosure;
class HeapInspection : public StackObj {
bool _csv_format; // "comma separated values" format for spreadsheet.
bool _print_help;
bool _print_class_stats;
const char* _columns;
public:
HeapInspection(bool csv_format, bool print_help,
bool print_class_stats, const char *columns) :
_csv_format(csv_format), _print_help(print_help),
_print_class_stats(print_class_stats), _columns(columns) {}
void heap_inspection(outputStream* st) NOT_SERVICES_RETURN;
size_t populate_table(KlassInfoTable* cit, BoolObjectClosure* filter = NULL) NOT_SERVICES_RETURN_(0);
static void find_instances_at_safepoint(Klass* k, GrowableArray<oop>* result) NOT_SERVICES_RETURN;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -25,7 +25,6 @@
#include "precompiled.hpp"
#include "classfile/classLoaderData.hpp"
#include "logging/log.hpp"
#include "memory/heapInspection.hpp"
#include "memory/metadataFactory.hpp"
#include "memory/metaspaceClosure.hpp"
#include "memory/oopFactory.hpp"
@ -89,37 +88,6 @@ void Annotations::print_value_on(outputStream* st) const {
st->print("Annotations(" INTPTR_FORMAT ")", p2i(this));
}
#if INCLUDE_SERVICES
// Size Statistics
julong Annotations::count_bytes(Array<AnnotationArray*>* p) {
julong bytes = 0;
if (p != NULL) {
for (int i = 0; i < p->length(); i++) {
bytes += KlassSizeStats::count_array(p->at(i));
}
bytes += KlassSizeStats::count_array(p);
}
return bytes;
}
void Annotations::collect_statistics(KlassSizeStats *sz) const {
sz->_annotations_bytes = sz->count(this);
sz->_class_annotations_bytes = sz->count(class_annotations());
sz->_class_type_annotations_bytes = sz->count(class_type_annotations());
sz->_fields_annotations_bytes = count_bytes(fields_annotations());
sz->_fields_type_annotations_bytes = count_bytes(fields_type_annotations());
sz->_annotations_bytes +=
sz->_class_annotations_bytes +
sz->_class_type_annotations_bytes +
sz->_fields_annotations_bytes +
sz->_fields_type_annotations_bytes;
sz->_ro_bytes += sz->_annotations_bytes;
}
#endif // INCLUDE_SERVICES
#define BULLET " - "
#ifndef PRODUCT

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -33,7 +33,6 @@
class ClassLoaderData;
class outputStream;
class KlassSizeStats;
typedef Array<u1> AnnotationArray;
@ -70,10 +69,6 @@ class Annotations: public MetaspaceObj {
// Annotations should be stored in the read-only region of CDS archive.
static bool is_read_only_by_default() { return true; }
#if INCLUDE_SERVICES
void collect_statistics(KlassSizeStats *sz) const;
#endif
// Constructor to initialize to null
Annotations() : _class_annotations(NULL),
_fields_annotations(NULL),

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -104,14 +104,6 @@ class ArrayKlass: public Klass {
virtual void metaspace_pointers_do(MetaspaceClosure* iter);
#if INCLUDE_SERVICES
virtual void collect_statistics(KlassSizeStats *sz) const {
Klass::collect_statistics(sz);
// Do nothing for now, but remember to modify if you add new
// stuff to ArrayKlass.
}
#endif
// Iterators
void array_klasses_do(void f(Klass* k));
void array_klasses_do(void f(Klass* k, TRAPS), TRAPS);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -24,7 +24,6 @@
#include "precompiled.hpp"
#include "interpreter/interpreter.hpp"
#include "memory/heapInspection.hpp"
#include "memory/metadataFactory.hpp"
#include "memory/metaspaceClosure.hpp"
#include "memory/resourceArea.hpp"
@ -454,36 +453,6 @@ void ConstMethod::print_value_on(outputStream* st) const {
}
}
#if INCLUDE_SERVICES
// Size Statistics
void ConstMethod::collect_statistics(KlassSizeStats *sz) const {
int n1, n2, n3;
sz->_const_method_bytes += (n1 = sz->count(this));
sz->_bytecode_bytes += (n2 = code_size());
sz->_stackmap_bytes += (n3 = sz->count_array(stackmap_data()));
// Count method annotations
int a1 = 0, a2 = 0, a3 = 0, a4 = 0;
if (has_method_annotations()) {
sz->_methods_annotations_bytes += (a1 = sz->count_array(method_annotations()));
}
if (has_parameter_annotations()) {
sz->_methods_parameter_annotations_bytes += (a2 = sz->count_array(parameter_annotations()));
}
if (has_type_annotations()) {
sz->_methods_type_annotations_bytes += (a3 = sz->count_array(type_annotations()));
}
if (has_default_annotations()) {
sz->_methods_default_annotations_bytes += (a4 = sz->count_array(default_annotations()));
}
int size_annotations = a1 + a2 + a3 + a4;
sz->_method_all_bytes += n1 + n3 + size_annotations; // note: n2 is part of n3
sz->_ro_bytes += n1 + n3 + size_annotations;
}
#endif // INCLUDE_SERVICES
// Verification
void ConstMethod::verify_on(outputStream* st) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -122,7 +122,6 @@ class MethodParametersElement {
u2 flags;
};
class KlassSizeStats;
class AdapterHandlerEntry;
// Class to collect the sizes of ConstMethod inline tables
@ -379,10 +378,6 @@ public:
// ConstMethods should be stored in the read-only region of CDS archive.
static bool is_read_only_by_default() { return true; }
#if INCLUDE_SERVICES
void collect_statistics(KlassSizeStats *sz) const;
#endif
// code size
int code_size() const { return _code_size; }
void set_code_size(int size) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -33,7 +33,6 @@
#include "interpreter/bootstrapInfo.hpp"
#include "interpreter/linkResolver.hpp"
#include "memory/allocation.inline.hpp"
#include "memory/heapInspection.hpp"
#include "memory/heapShared.hpp"
#include "memory/metadataFactory.hpp"
#include "memory/metaspaceClosure.hpp"
@ -2379,21 +2378,6 @@ void ConstantPool::print_value_on(outputStream* st) const {
}
}
#if INCLUDE_SERVICES
// Size Statistics
void ConstantPool::collect_statistics(KlassSizeStats *sz) const {
sz->_cp_all_bytes += (sz->_cp_bytes = sz->count(this));
sz->_cp_all_bytes += (sz->_cp_tags_bytes = sz->count_array(tags()));
sz->_cp_all_bytes += (sz->_cp_cache_bytes = sz->count(cache()));
sz->_cp_all_bytes += (sz->_cp_operands_bytes = sz->count_array(operands()));
sz->_cp_all_bytes += (sz->_cp_refmap_bytes = sz->count_array(reference_map()));
sz->_ro_bytes += sz->_cp_operands_bytes + sz->_cp_tags_bytes +
sz->_cp_refmap_bytes;
sz->_rw_bytes += sz->_cp_bytes + sz->_cp_cache_bytes;
}
#endif // INCLUDE_SERVICES
// Verification
void ConstantPool::verify_on(outputStream* st) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -93,8 +93,6 @@ public:
}
};
class KlassSizeStats;
class ConstantPool : public Metadata {
friend class VMStructs;
friend class JVMCIVMStructs;
@ -773,9 +771,6 @@ class ConstantPool : public Metadata {
}
static int size(int length) { return align_metadata_size(header_size() + length); }
int size() const { return size(length()); }
#if INCLUDE_SERVICES
void collect_statistics(KlassSizeStats *sz) const;
#endif
// ConstantPools should be stored in the read-only region of CDS archive.
static bool is_read_only_by_default() { return true; }

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -46,7 +46,6 @@
#include "logging/logMessage.hpp"
#include "logging/logStream.hpp"
#include "memory/allocation.inline.hpp"
#include "memory/heapInspection.hpp"
#include "memory/iterator.inline.hpp"
#include "memory/metadataFactory.hpp"
#include "memory/metaspaceClosure.hpp"
@ -3541,61 +3540,6 @@ void InstanceKlass::print_class_load_logging(ClassLoaderData* loader_data,
}
}
#if INCLUDE_SERVICES
// Size Statistics
void InstanceKlass::collect_statistics(KlassSizeStats *sz) const {
Klass::collect_statistics(sz);
sz->_inst_size = wordSize * size_helper();
sz->_vtab_bytes = wordSize * vtable_length();
sz->_itab_bytes = wordSize * itable_length();
sz->_nonstatic_oopmap_bytes = wordSize * nonstatic_oop_map_size();
int n = 0;
n += (sz->_methods_array_bytes = sz->count_array(methods()));
n += (sz->_method_ordering_bytes = sz->count_array(method_ordering()));
n += (sz->_local_interfaces_bytes = sz->count_array(local_interfaces()));
n += (sz->_transitive_interfaces_bytes = sz->count_array(transitive_interfaces()));
n += (sz->_fields_bytes = sz->count_array(fields()));
n += (sz->_inner_classes_bytes = sz->count_array(inner_classes()));
n += (sz->_nest_members_bytes = sz->count_array(nest_members()));
n += (sz->_record_components_bytes = sz->count_array(record_components()));
sz->_ro_bytes += n;
const ConstantPool* cp = constants();
if (cp) {
cp->collect_statistics(sz);
}
const Annotations* anno = annotations();
if (anno) {
anno->collect_statistics(sz);
}
const Array<Method*>* methods_array = methods();
if (methods()) {
for (int i = 0; i < methods_array->length(); i++) {
Method* method = methods_array->at(i);
if (method) {
sz->_method_count ++;
method->collect_statistics(sz);
}
}
}
const Array<RecordComponent*>* components = record_components();
if (components != NULL) {
for (int i = 0; i < components->length(); i++) {
RecordComponent* component = components->at(i);
if (component != NULL) {
component->collect_statistics(sz);
}
}
}
}
#endif // INCLUDE_SERVICES
// Verification
class VerifyFieldClosure: public BasicOopIterateClosure {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -1066,9 +1066,6 @@ public:
is_unsafe_anonymous(),
has_stored_fingerprint());
}
#if INCLUDE_SERVICES
virtual void collect_statistics(KlassSizeStats *sz) const;
#endif
intptr_t* start_of_itable() const { return (intptr_t*)start_of_vtable() + vtable_length(); }
intptr_t* end_of_itable() const { return start_of_itable() + itable_length(); }

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -32,7 +32,6 @@
#include "classfile/vmSymbols.hpp"
#include "gc/shared/collectedHeap.inline.hpp"
#include "logging/log.hpp"
#include "memory/heapInspection.hpp"
#include "memory/heapShared.hpp"
#include "memory/metadataFactory.hpp"
#include "memory/metaspaceClosure.hpp"
@ -756,18 +755,6 @@ void Klass::oop_print_value_on(oop obj, outputStream* st) {
obj->print_address_on(st);
}
#if INCLUDE_SERVICES
// Size Statistics
void Klass::collect_statistics(KlassSizeStats *sz) const {
sz->_klass_bytes = sz->count(this);
sz->_mirror_bytes = sz->count(java_mirror_no_keepalive());
sz->_secondary_supers_bytes = sz->count_array(secondary_supers());
sz->_ro_bytes += sz->_secondary_supers_bytes;
sz->_rw_bytes += sz->_klass_bytes + sz->_mirror_bytes;
}
#endif // INCLUDE_SERVICES
// Verification
void Klass::verify_on(outputStream* st) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -68,7 +68,6 @@ const uint KLASS_ID_COUNT = 6;
template <class T> class Array;
template <class T> class GrowableArray;
class fieldDescriptor;
class KlassSizeStats;
class klassVtable;
class ModuleEntry;
class PackageEntry;
@ -541,9 +540,6 @@ protected:
// Size of klass in word size.
virtual int size() const = 0;
#if INCLUDE_SERVICES
virtual void collect_statistics(KlassSizeStats *sz) const;
#endif
// Returns the Java name for a class (Resource allocated)
// For arrays, this returns the name of the element with a leading '['.

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -39,7 +39,6 @@
#include "logging/log.hpp"
#include "logging/logTag.hpp"
#include "memory/allocation.inline.hpp"
#include "memory/heapInspection.hpp"
#include "memory/metadataFactory.hpp"
#include "memory/metaspaceClosure.hpp"
#include "memory/metaspaceShared.hpp"
@ -2427,23 +2426,6 @@ void Method::print_value_on(outputStream* st) const {
if (WizardMode && code() != NULL) st->print(" ((nmethod*)%p)", code());
}
#if INCLUDE_SERVICES
// Size Statistics
void Method::collect_statistics(KlassSizeStats *sz) const {
int mysize = sz->count(this);
sz->_method_bytes += mysize;
sz->_method_all_bytes += mysize;
sz->_rw_bytes += mysize;
if (constMethod()) {
constMethod()->collect_statistics(sz);
}
if (method_data()) {
method_data()->collect_statistics(sz);
}
}
#endif // INCLUDE_SERVICES
// LogTouchedMethods and PrintTouchedMethods
// TouchedMethodRecord -- we can't use a HashtableEntry<Method*> because

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -64,7 +64,6 @@ class MethodData;
class MethodCounters;
class ConstMethod;
class InlineTableSizes;
class KlassSizeStats;
class CompiledMethod;
class InterpreterOopMap;
@ -713,9 +712,6 @@ public:
}
static int size(bool is_native);
int size() const { return method_size(); }
#if INCLUDE_SERVICES
void collect_statistics(KlassSizeStats *sz) const;
#endif
void log_touched(TRAPS);
static void print_touched_methods(outputStream* out);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -29,7 +29,6 @@
#include "interpreter/bytecode.hpp"
#include "interpreter/bytecodeStream.hpp"
#include "interpreter/linkResolver.hpp"
#include "memory/heapInspection.hpp"
#include "memory/metaspaceClosure.hpp"
#include "memory/resourceArea.hpp"
#include "oops/methodData.inline.hpp"
@ -1576,16 +1575,6 @@ void MethodData::print_data_on(outputStream* st) const {
}
}
#if INCLUDE_SERVICES
// Size Statistics
void MethodData::collect_statistics(KlassSizeStats *sz) const {
int n = sz->count(this);
sz->_method_data_bytes += n;
sz->_method_all_bytes += n;
sz->_rw_bytes += n;
}
#endif // INCLUDE_SERVICES
// Verification
void MethodData::verify_on(outputStream* st) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -33,7 +33,6 @@
#include "utilities/align.hpp"
class BytecodeStream;
class KlassSizeStats;
// The MethodData object collects counts and other profile information
// during zeroth-tier (interpretive) and first-tier execution.
@ -2181,9 +2180,6 @@ public:
// My size
int size_in_bytes() const { return _size; }
int size() const { return align_metadata_size(align_up(_size, BytesPerWord)/BytesPerWord); }
#if INCLUDE_SERVICES
void collect_statistics(KlassSizeStats *sz) const;
#endif
int creation_mileage() const { return _creation_mileage; }
void set_creation_mileage(int x) { _creation_mileage = x; }

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -24,7 +24,6 @@
#include "precompiled.hpp"
#include "logging/log.hpp"
#include "memory/heapInspection.hpp"
#include "memory/metadataFactory.hpp"
#include "memory/metaspace.hpp"
#include "memory/metaspaceClosure.hpp"
@ -63,19 +62,6 @@ void RecordComponent::print_value_on(outputStream* st) const {
st->print("RecordComponent(" INTPTR_FORMAT ")", p2i(this));
}
#if INCLUDE_SERVICES
void RecordComponent::collect_statistics(KlassSizeStats *sz) const {
if (_annotations != NULL) {
sz->_annotations_bytes += sz->count(_annotations);
sz->_ro_bytes += sz->count(_annotations);
}
if (_type_annotations != NULL) {
sz->_annotations_bytes += sz->count(_type_annotations);
sz->_ro_bytes += sz->count(_type_annotations);
}
}
#endif
#ifndef PRODUCT
void RecordComponent::print_on(outputStream* st) const {
st->print("name_index: %d", _name_index);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -29,8 +29,6 @@
#include "oops/metadata.hpp"
#include "utilities/globalDefinitions.hpp"
class KlassSizeStats;
// This class stores information extracted from the Record class attribute.
class RecordComponent: public MetaspaceObj {
private:
@ -91,10 +89,6 @@ class RecordComponent: public MetaspaceObj {
static bool is_read_only_by_default() { return true; }
DEBUG_ONLY(bool on_stack() { return false; }) // for template
#if INCLUDE_SERVICES
void collect_statistics(KlassSizeStats *sz) const;
#endif
bool is_klass() const { return false; }
#ifndef PRODUCT

View File

@ -2200,6 +2200,12 @@ WB_ENTRY(jint, WB_AotLibrariesCount(JNIEnv* env, jobject o))
return result;
WB_END
WB_ENTRY(jint, WB_GetKlassMetadataSize(JNIEnv* env, jobject wb, jclass mirror))
Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve(mirror));
// Return size in bytes.
return k->size() * wordSize;
WB_END
#define CC (char*)
static JNINativeMethod methods[] = {
@ -2442,6 +2448,7 @@ static JNINativeMethod methods[] = {
{CC"resolvedMethodItemsCount", CC"()J", (void*)&WB_ResolvedMethodItemsCount },
{CC"protectionDomainRemovedCount", CC"()I", (void*)&WB_ProtectionDomainRemovedCount },
{CC"aotLibrariesCount", CC"()I", (void*)&WB_AotLibrariesCount },
{CC"getKlassMetadataSize", CC"(Ljava/lang/Class;)I",(void*)&WB_GetKlassMetadataSize},
};

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -90,7 +90,6 @@ void DCmdRegistrant::register_dcmds(){
#if INCLUDE_SERVICES
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<HeapDumpDCmd>(DCmd_Source_Internal | DCmd_Source_AttachAPI, true, false));
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<ClassHistogramDCmd>(full_export, true, false));
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<ClassStatsDCmd>(full_export, true, false));
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<SystemDictionaryDCmd>(full_export, true, false));
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<ClassHierarchyDCmd>(full_export, true, false));
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<SymboltableDCmd>(full_export, true, false));
@ -554,57 +553,6 @@ int ClassHistogramDCmd::num_arguments() {
}
}
#define DEFAULT_COLUMNS "InstBytes,KlassBytes,CpAll,annotations,MethodCount,Bytecodes,MethodAll,ROAll,RWAll,Total"
ClassStatsDCmd::ClassStatsDCmd(outputStream* output, bool heap) :
DCmdWithParser(output, heap),
_all("-all", "Show all columns",
"BOOLEAN", false, "false"),
_csv("-csv", "Print in CSV (comma-separated values) format for spreadsheets",
"BOOLEAN", false, "false"),
_help("-help", "Show meaning of all the columns",
"BOOLEAN", false, "false"),
_columns("columns", "Comma-separated list of all the columns to show. "
"If not specified, the following columns are shown: " DEFAULT_COLUMNS,
"STRING", false) {
_dcmdparser.add_dcmd_option(&_all);
_dcmdparser.add_dcmd_option(&_csv);
_dcmdparser.add_dcmd_option(&_help);
_dcmdparser.add_dcmd_argument(&_columns);
}
void ClassStatsDCmd::execute(DCmdSource source, TRAPS) {
VM_GC_HeapInspection heapop(output(),
true /* request_full_gc */);
heapop.set_csv_format(_csv.value());
heapop.set_print_help(_help.value());
heapop.set_print_class_stats(true);
if (_all.value()) {
if (_columns.has_value()) {
output()->print_cr("Cannot specify -all and individual columns at the same time");
return;
} else {
heapop.set_columns(NULL);
}
} else {
if (_columns.has_value()) {
heapop.set_columns(_columns.value());
} else {
heapop.set_columns(DEFAULT_COLUMNS);
}
}
VMThread::execute(&heapop);
}
int ClassStatsDCmd::num_arguments() {
ResourceMark rm;
ClassStatsDCmd* dcmd = new ClassStatsDCmd(NULL, false);
if (dcmd != NULL) {
DCmdMark mark(dcmd);
return dcmd->_dcmdparser.num_arguments();
} else {
return 0;
}
}
#endif // INCLUDE_SERVICES
ThreadDumpDCmd::ThreadDumpDCmd(outputStream* output, bool heap) :

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -376,28 +376,6 @@ public:
virtual void execute(DCmdSource source, TRAPS);
};
class ClassStatsDCmd : public DCmdWithParser {
protected:
DCmdArgument<bool> _all;
DCmdArgument<bool> _csv;
DCmdArgument<bool> _help;
DCmdArgument<char*> _columns;
public:
ClassStatsDCmd(outputStream* output, bool heap);
static const char* name() {
return "GC.class_stats";
}
static const char* description() {
return "(Deprecated) Provide statistics about Java class meta data.";
}
static const char* impact() {
return "High: Depends on Java heap size and content.";
}
static int num_arguments();
virtual void execute(DCmdSource source, TRAPS);
};
class ClassHierarchyDCmd : public DCmdWithParser {
protected:
DCmdArgument<bool> _print_interfaces; // true if inherited interfaces should be printed.

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -50,40 +50,23 @@ import java.util.*;
* jdk.hotspot.agent/sun.jvm.hotspot.utilities
* jdk.hotspot.agent/sun.jvm.hotspot.oops
* jdk.hotspot.agent/sun.jvm.hotspot.debugger
* @run main/othervm TestInstanceKlassSize
* @build sun.hotspot.WhiteBox
* @run driver ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission
* @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. TestInstanceKlassSize
*/
import sun.hotspot.WhiteBox;
public class TestInstanceKlassSize {
private static String getJcmdInstanceKlassSize(OutputAnalyzer output,
String instanceKlassName) {
for (String s : output.asLines()) {
if (s.contains(instanceKlassName)) {
String tokens[];
System.out.println(s);
tokens = s.split("\\s+");
return tokens[3];
}
}
return null;
}
private static OutputAnalyzer jcmd(Long pid,
String... toolArgs) throws Exception {
ProcessBuilder processBuilder = new ProcessBuilder();
JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jcmd");
launcher.addToolArg(Long.toString(pid));
if (toolArgs != null) {
for (String toolArg : toolArgs) {
launcher.addToolArg(toolArg);
}
}
processBuilder.command(launcher.getCommand());
System.out.println(
processBuilder.command().stream().collect(Collectors.joining(" ")));
return ProcessTools.executeProcess(processBuilder);
}
public static WhiteBox wb = WhiteBox.getWhiteBox();
private static String[] SAInstanceKlassNames = new String[] {
"java.lang.Object",
"java.util.Vector",
"java.lang.String",
"java.lang.Thread",
"java.lang.Byte"
};
private static void startMeWithArgs() throws Exception {
@ -100,48 +83,41 @@ public class TestInstanceKlassSize {
throw new RuntimeException(ex);
}
try {
String[] instanceKlassNames = new String[] {
" java.lang.Object",
" java.util.Vector",
" java.lang.String",
" java.lang.Thread",
" java.lang.Byte",
};
// Run this app with the LingeredApp PID to get SA output from the LingeredApp
String[] toolArgs = {
"--add-modules=jdk.hotspot.agent",
"--add-exports=jdk.hotspot.agent/sun.jvm.hotspot=ALL-UNNAMED",
"--add-exports=jdk.hotspot.agent/sun.jvm.hotspot.utilities=ALL-UNNAMED",
"--add-exports=jdk.hotspot.agent/sun.jvm.hotspot.oops=ALL-UNNAMED",
"--add-exports=jdk.hotspot.agent/sun.jvm.hotspot.debugger=ALL-UNNAMED",
"-XX:+UnlockDiagnosticVMOptions",
"-XX:+WhiteBoxAPI",
"-Xbootclasspath/a:.",
"TestInstanceKlassSize",
Long.toString(app.getPid())
};
OutputAnalyzer jcmdOutput = jcmd(
app.getPid(),
"GC.class_stats", "VTab,ITab,OopMap,KlassBytes");
ProcessBuilder processBuilder = ProcessTools
.createJavaProcessBuilder(toolArgs);
output = ProcessTools.executeProcess(processBuilder);
System.out.println(output.getOutput());
output.shouldHaveExitValue(0);
// Check whether the size matches that which jcmd outputs
for (String instanceKlassName : instanceKlassNames) {
System.out.println ("Trying to match for" + instanceKlassName);
String jcmdInstanceKlassSize = getJcmdInstanceKlassSize(
jcmdOutput,
instanceKlassName);
Asserts.assertNotNull(jcmdInstanceKlassSize,
"Could not get the instance klass size from the jcmd output");
// Check whether the size matches with value from VM.
for (String instanceKlassName : SAInstanceKlassNames) {
Class<?> iklass = Class.forName(instanceKlassName);
System.out.println ("Trying to match for " + instanceKlassName);
String size = String.valueOf(wb.getKlassMetadataSize(iklass));
boolean match = false;
for (String s : output.asLines()) {
if (s.contains(instanceKlassName)) {
Asserts.assertTrue(
s.contains(jcmdInstanceKlassSize),
"The size computed by SA for" +
s.contains(size), "The size computed by SA for" +
instanceKlassName + " does not match.");
match = true;
}
}
Asserts.assertTrue(match, "Found a match for " + instanceKlassName);
}
} finally {
LingeredApp.stopApp(app);
@ -179,13 +155,6 @@ public class TestInstanceKlassSize {
System.out.println ("No args run. Starting with args now.");
startMeWithArgs();
} else {
String[] SAInstanceKlassNames = new String[] {
"java.lang.Object",
"java.util.Vector",
"java.lang.String",
"java.lang.Thread",
"java.lang.Byte"
};
SAInstanceKlassSize(Integer.parseInt(args[0]), SAInstanceKlassNames);
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -47,11 +47,17 @@ import jdk.test.lib.Asserts;
* jdk.hotspot.agent/sun.jvm.hotspot.utilities
* jdk.hotspot.agent/sun.jvm.hotspot.oops
* jdk.hotspot.agent/sun.jvm.hotspot.debugger
* @run main/othervm TestInstanceKlassSizeForInterface
* @build sun.hotspot.WhiteBox
* @run driver ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission
* @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. TestInstanceKlassSize
*/
import sun.hotspot.WhiteBox;
public class TestInstanceKlassSizeForInterface {
public static WhiteBox wb = WhiteBox.getWhiteBox();
private static LingeredAppWithInterface theApp = null;
private static void SAInstanceKlassSize(int lingeredAppPid,
@ -103,6 +109,9 @@ public class TestInstanceKlassSizeForInterface {
"--add-exports=jdk.hotspot.agent/sun.jvm.hotspot.utilities=ALL-UNNAMED",
"--add-exports=jdk.hotspot.agent/sun.jvm.hotspot.oops=ALL-UNNAMED",
"--add-exports=jdk.hotspot.agent/sun.jvm.hotspot.debugger=ALL-UNNAMED",
"-XX:+UnlockDiagnosticVMOptions",
"-XX:+WhiteBoxAPI",
"-Xbootclasspath/a:.",
"TestInstanceKlassSizeForInterface",
Integer.toString(lingeredAppPid)
};
@ -114,35 +123,21 @@ public class TestInstanceKlassSizeForInterface {
SAOutput.shouldHaveExitValue(0);
System.out.println(SAOutput.getOutput());
// Run jcmd on the LingeredApp process
ProcessBuilder pb = new ProcessBuilder();
pb.command(new String[] {
JDKToolFinder.getJDKTool("jcmd"),
Long.toString(lingeredAppPid),
"GC.class_stats",
"VTab,ITab,OopMap,KlassBytes"
}
);
OutputAnalyzer jcmdOutput = new OutputAnalyzer(pb.start());
System.out.println(jcmdOutput.getOutput());
// Match the sizes from both the output streams
for (String instanceKlassName : instanceKlassNames) {
Class<?> iklass = Class.forName(instanceKlassName);
System.out.println ("Trying to match for " + instanceKlassName);
String jcmdInstanceKlassSize = getJcmdInstanceKlassSize(
jcmdOutput,
instanceKlassName);
Asserts.assertNotNull(jcmdInstanceKlassSize,
"Could not get the instance klass size from the jcmd output");
String size = String.valueOf(wb.getKlassMetadataSize(iklass));
boolean match = false;
for (String s : SAOutput.asLines()) {
if (s.contains(instanceKlassName)) {
Asserts.assertTrue(
s.contains(jcmdInstanceKlassSize),
"The size computed by SA for " +
instanceKlassName + " does not match.");
}
Asserts.assertTrue(
s.contains(size), "The size computed by SA for" +
instanceKlassName + " does not match.");
match = true;
}
}
Asserts.assertTrue(match, "Found a match for " + instanceKlassName);
}
}

View File

@ -559,4 +559,6 @@ public class WhiteBox {
// Number of loaded AOT libraries
public native int aotLibrariesCount();
public native int getKlassMetadataSize(Class<?> c);
}