< prev index next > src/hotspot/share/memory/universe.cpp
Print this page
/*
! * Copyright (c) 1997, 2025, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
/*
! * Copyright (c) 1997, 2026, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
#include "oops/jmethodIDTable.hpp"
#include "oops/klass.inline.hpp"
#include "oops/objArrayOop.inline.hpp"
#include "oops/objLayout.hpp"
#include "oops/oop.inline.hpp"
+ #include "oops/oopCast.inline.hpp"
#include "oops/oopHandle.inline.hpp"
+ #include "oops/refArrayKlass.hpp"
#include "oops/typeArrayKlass.hpp"
#include "prims/resolvedMethodTable.hpp"
#include "runtime/arguments.hpp"
#include "runtime/atomicAccess.hpp"
#include "runtime/cpuTimeCounters.hpp"
static LatestMethodCache _finalizer_register_cache; // Finalizer.register()
static LatestMethodCache _loader_addClass_cache; // ClassLoader.addClass()
static LatestMethodCache _throw_illegal_access_error_cache; // Unsafe.throwIllegalAccessError()
static LatestMethodCache _throw_no_such_method_error_cache; // Unsafe.throwNoSuchMethodError()
static LatestMethodCache _do_stack_walk_cache; // AbstractStackWalker.doStackWalk()
+ static LatestMethodCache _is_substitutable_cache; // ValueObjectMethods.isSubstitutable()
+ static LatestMethodCache _value_object_hash_code_cache; // ValueObjectMethods.valueObjectHashCode()
// Known objects
TypeArrayKlass* Universe::_typeArrayKlasses[T_LONG+1] = { nullptr /*, nullptr...*/ };
ObjArrayKlass* Universe::_objectArrayKlass = nullptr;
Klass* Universe::_fillerArrayKlass = nullptr;
// Since some of the old system object arrays have been converted to
// ordinary object arrays, _objectArrayKlass will be loaded when
// SystemDictionary::initialize(CHECK); is run. See the extra check
// for Object_klass_is_loaded in ObjArrayKlass::allocate_objArray_klass.
{
! Klass* oak = vmClasses::Object_klass()->array_klass(CHECK);
! _objectArrayKlass = ObjArrayKlass::cast(oak);
}
- // OLD
- // Add the class to the class hierarchy manually to make sure that
- // its vtable is initialized after core bootstrapping is completed.
- // ---
- // New
- // Have already been initialized.
- _objectArrayKlass->append_to_sibling_list();
#ifdef ASSERT
if (FullGCALot) {
// Allocate an array of dummy objects.
// We'd like these to be at the bottom of the old generation,
// Since some of the old system object arrays have been converted to
// ordinary object arrays, _objectArrayKlass will be loaded when
// SystemDictionary::initialize(CHECK); is run. See the extra check
// for Object_klass_is_loaded in ObjArrayKlass::allocate_objArray_klass.
{
! ArrayKlass* oak = vmClasses::Object_klass()->array_klass(CHECK);
! oak->append_to_sibling_list();
+
+ // Create a RefArrayKlass (which is the default) and initialize.
+ ObjArrayKlass* rak = ObjArrayKlass::cast(oak)->klass_with_properties(ArrayProperties::Default(), THREAD);
+ _objectArrayKlass = rak;
}
#ifdef ASSERT
if (FullGCALot) {
// Allocate an array of dummy objects.
// We'd like these to be at the bottom of the old generation,
// classes are always initialized first.
for (ClassHierarchyIterator iter(vmClasses::Object_klass()); !iter.done(); iter.next()) {
Klass* sub = iter.klass();
sub->vtable().initialize_vtable();
}
+
+ // This isn't added to the subclass list, so need to reinitialize vtables directly.
+ Universe::objectArrayKlass()->vtable().initialize_vtable();
}
static void reinitialize_itables() {
class ReinitTableClosure : public KlassClosure {
bool Universe::on_page_boundary(void* addr) {
return is_aligned(addr, os::vm_page_size());
}
// the array of preallocated errors with backtraces
! objArrayOop Universe::preallocated_out_of_memory_errors() {
! return (objArrayOop)_preallocated_out_of_memory_error_array.resolve();
}
! objArrayOop Universe::out_of_memory_errors() { return (objArrayOop)_out_of_memory_errors.resolve(); }
oop Universe::out_of_memory_error_java_heap() {
return gen_out_of_memory_error(out_of_memory_errors()->obj_at(_oom_java_heap));
}
bool Universe::on_page_boundary(void* addr) {
return is_aligned(addr, os::vm_page_size());
}
// the array of preallocated errors with backtraces
! refArrayOop Universe::preallocated_out_of_memory_errors() {
! return oop_cast<refArrayOop>(_preallocated_out_of_memory_error_array.resolve());
}
! refArrayOop Universe::out_of_memory_errors() { return oop_cast<refArrayOop>(_out_of_memory_errors.resolve()); }
oop Universe::out_of_memory_error_java_heap() {
return gen_out_of_memory_error(out_of_memory_errors()->obj_at(_oom_java_heap));
}
// never attempt to fill in the stack trace of preallocated errors that do not have
// backtrace. These errors are kept alive forever and may be "re-used" when all
// preallocated errors with backtrace have been consumed. Also need to avoid
// a potential loop which could happen if an out of memory occurs when attempting
// to allocate the backtrace.
! objArrayOop preallocated_oom = out_of_memory_errors();
for (int i = 0; i < _oom_count; i++) {
if (throwable() == preallocated_oom->obj_at(i)) {
return false;
}
}
// never attempt to fill in the stack trace of preallocated errors that do not have
// backtrace. These errors are kept alive forever and may be "re-used" when all
// preallocated errors with backtrace have been consumed. Also need to avoid
// a potential loop which could happen if an out of memory occurs when attempting
// to allocate the backtrace.
! refArrayOop preallocated_oom = out_of_memory_errors();
for (int i = 0; i < _oom_count; i++) {
if (throwable() == preallocated_oom->obj_at(i)) {
return false;
}
}
}
// Setup preallocated OutOfMemoryError errors
void Universe::create_preallocated_out_of_memory_errors(TRAPS) {
InstanceKlass* ik = vmClasses::OutOfMemoryError_klass();
! objArrayOop oa = oopFactory::new_objArray(ik, _oom_count, CHECK);
! objArrayHandle oom_array(THREAD, oa);
for (int i = 0; i < _oom_count; i++) {
oop oom_obj = ik->allocate_instance(CHECK);
oom_array->obj_at_put(i, oom_obj);
}
}
// Setup preallocated OutOfMemoryError errors
void Universe::create_preallocated_out_of_memory_errors(TRAPS) {
InstanceKlass* ik = vmClasses::OutOfMemoryError_klass();
! refArrayOop ra = oopFactory::new_refArray(ik, _oom_count, CHECK);
! refArrayHandle oom_array(THREAD, ra);
for (int i = 0; i < _oom_count; i++) {
oop oom_obj = ik->allocate_instance(CHECK);
oom_array->obj_at_put(i, oom_obj);
}
msg = java_lang_String::create_from_str("Java heap space: failed reallocation of scalar replaced objects", CHECK);
java_lang_Throwable::set_message(oom_array->obj_at(_oom_realloc_objects), msg());
// Setup the array of errors that have preallocated backtrace
int len = (StackTraceInThrowable) ? (int)PreallocatedOutOfMemoryErrorCount : 0;
! objArrayOop instance = oopFactory::new_objArray(ik, len, CHECK);
_preallocated_out_of_memory_error_array = OopHandle(vm_global(), instance);
! objArrayHandle preallocated_oom_array(THREAD, instance);
for (int i=0; i<len; i++) {
oop err = ik->allocate_instance(CHECK);
Handle err_h(THREAD, err);
java_lang_Throwable::allocate_backtrace(err_h, CHECK);
msg = java_lang_String::create_from_str("Java heap space: failed reallocation of scalar replaced objects", CHECK);
java_lang_Throwable::set_message(oom_array->obj_at(_oom_realloc_objects), msg());
// Setup the array of errors that have preallocated backtrace
int len = (StackTraceInThrowable) ? (int)PreallocatedOutOfMemoryErrorCount : 0;
! refArrayOop instance = oopFactory::new_refArray(ik, len, CHECK);
_preallocated_out_of_memory_error_array = OopHandle(vm_global(), instance);
! refArrayHandle preallocated_oom_array(THREAD, instance);
for (int i=0; i<len; i++) {
oop err = ik->allocate_instance(CHECK);
Handle err_h(THREAD, err);
java_lang_Throwable::allocate_backtrace(err_h, CHECK);
assert(m != nullptr, "sanity check");
return m;
}
}
! Method* Universe::finalizer_register_method() { return _finalizer_register_cache.get_method(); }
! Method* Universe::loader_addClass_method() { return _loader_addClass_cache.get_method(); }
! Method* Universe::throw_illegal_access_error() { return _throw_illegal_access_error_cache.get_method(); }
! Method* Universe::throw_no_such_method_error() { return _throw_no_such_method_error_cache.get_method(); }
! Method* Universe::do_stack_walk_method() { return _do_stack_walk_cache.get_method(); }
void Universe::initialize_known_methods(JavaThread* current) {
// Set up static method for registering finalizers
_finalizer_register_cache.init(current,
vmClasses::Finalizer_klass(),
assert(m != nullptr, "sanity check");
return m;
}
}
! Method* Universe::finalizer_register_method() { return _finalizer_register_cache.get_method(); }
! Method* Universe::loader_addClass_method() { return _loader_addClass_cache.get_method(); }
! Method* Universe::throw_illegal_access_error() { return _throw_illegal_access_error_cache.get_method(); }
! Method* Universe::throw_no_such_method_error() { return _throw_no_such_method_error_cache.get_method(); }
! Method* Universe::do_stack_walk_method() { return _do_stack_walk_cache.get_method(); }
+ Method* Universe::is_substitutable_method() { return _is_substitutable_cache.get_method(); }
+ Method* Universe::value_object_hash_code_method() { return _value_object_hash_code_cache.get_method(); }
void Universe::initialize_known_methods(JavaThread* current) {
// Set up static method for registering finalizers
_finalizer_register_cache.init(current,
vmClasses::Finalizer_klass(),
// Set up method for stack walking
_do_stack_walk_cache.init(current,
vmClasses::AbstractStackWalker_klass(),
"doStackWalk",
vmSymbols::doStackWalk_signature(), false);
+
+ // Set up substitutability testing
+ ResourceMark rm(current);
+ _is_substitutable_cache.init(current,
+ vmClasses::ValueObjectMethods_klass(),
+ vmSymbols::isSubstitutable_name()->as_C_string(),
+ vmSymbols::object_object_boolean_signature(), true);
+ _value_object_hash_code_cache.init(current,
+ vmClasses::ValueObjectMethods_klass(),
+ vmSymbols::valueObjectHashCode_name()->as_C_string(),
+ vmSymbols::object_int_signature(), true);
}
void universe2_init() {
EXCEPTION_MARK;
Universe::genesis(CATCH);
< prev index next >