Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

8329706: Implement -XX:+AOTClassLinking #20843

Closed
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/hotspot/share/cds/aotClassLinker.hpp
Original file line number Diff line number Diff line change
@@ -98,12 +98,12 @@ class AOTClassLinker : AllStatic {

// When CDS is enabled, is ik guatanteed to be linked at deployment time (and
// cannot be replaced by JVMTI, etc)?
// This is a necessary (not but sufficient) condition for keeping a direct pointer
// This is a necessary (but not sufficient) condition for keeping a direct pointer
// to ik in AOT-computed data (such as ConstantPool entries in archived classes,
// or in AOT-compiled code).
static bool is_candidate(InstanceKlass* ik);

// Request that ik to be added to the candidates table. This will return succeed only if
// Request that ik be added to the candidates table. This will return true only if
// ik is allowed to be aot-linked.
static bool try_add_candidate(InstanceKlass* ik);

51 changes: 27 additions & 24 deletions src/hotspot/share/cds/aotLinkedClassBulkLoader.cpp
Original file line number Diff line number Diff line change
@@ -28,28 +28,19 @@
#include "cds/archiveBuilder.hpp"
#include "cds/archiveUtils.inline.hpp"
#include "cds/cdsConfig.hpp"
#include "cds/cdsProtectionDomain.hpp"
#include "cds/heapShared.hpp"
#include "cds/lambdaFormInvokers.inline.hpp"
#include "classfile/classLoader.hpp"
#include "classfile/classLoaderDataGraph.hpp"
#include "classfile/classLoaderExt.hpp"
#include "classfile/dictionary.hpp"
#include "classfile/javaClasses.hpp"
#include "classfile/systemDictionary.hpp"
#include "classfile/systemDictionaryShared.hpp"
#include "classfile/vmClasses.hpp"
#include "compiler/compilationPolicy.hpp"
#include "gc/shared/gcVMOperations.hpp"
#include "memory/resourceArea.hpp"
#include "oops/constantPool.inline.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/klass.inline.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/javaCalls.hpp"
#include "runtime/perfData.inline.hpp"
#include "runtime/timer.hpp"
#include "services/management.hpp"
#include "runtime/java.hpp"

void AOTLinkedClassBulkLoader::serialize(SerializeClosure* soc, bool is_static_archive) {
AOTLinkedClassTable::get(is_static_archive)->serialize(soc);
@@ -72,21 +63,33 @@ void AOTLinkedClassBulkLoader::load_app_classes(JavaThread* current) {
}

void AOTLinkedClassBulkLoader::load_classes_in_loader(JavaThread* current, LoaderKind loader_kind, oop class_loader_oop) {
if (!CDSConfig::is_using_aot_linked_classes()) {
return;
}

HandleMark hm(current);
ResourceMark rm(current);
ExceptionMark em(current);
ResourceMark rm(current);
HandleMark hm(current);

Handle h_loader(current, class_loader_oop);
load_classes_in_loader_impl(loader_kind, class_loader_oop, current);
if (current->has_pending_exception()) {
// We cannot continue, as we might have loaded some of the aot-linked classes, which
// may have dangling C++ pointers to other aot-linked classes that we have failed to load.
if (current->pending_exception()->is_a(vmClasses::OutOfMemoryError_klass())) {
log_error(cds)("Out of memory. Please run with a larger Java heap, current MaxHeapSize = "
SIZE_FORMAT "M", MaxHeapSize/M);
} else {
log_error(cds)("%s: %s", current->pending_exception()->klass()->external_name(),
java_lang_String::as_utf8_string(java_lang_Throwable::message(current->pending_exception())));
}
vm_exit_during_initialization("Unexpected exception when loading aot-linked classes.");
}
}

load_table(AOTLinkedClassTable::for_static_archive(), loader_kind, h_loader, current);
assert(!current->has_pending_exception(), "VM should have exited due to ExceptionMark");
void AOTLinkedClassBulkLoader::load_classes_in_loader_impl(LoaderKind loader_kind, oop class_loader_oop, TRAPS) {
if (!CDSConfig::is_using_aot_linked_classes()) {
return;
}

load_table(AOTLinkedClassTable::for_dynamic_archive(), loader_kind, h_loader, current);
assert(!current->has_pending_exception(), "VM should have exited due to ExceptionMark");
Handle h_loader(THREAD, class_loader_oop);
load_table(AOTLinkedClassTable::for_static_archive(), loader_kind, h_loader, CHECK);
load_table(AOTLinkedClassTable::for_dynamic_archive(), loader_kind, h_loader, CHECK);

if (Universe::is_fully_initialized() && VerifyDuringStartup) {
// Make sure we're still in a clean slate.
@@ -140,7 +143,7 @@ void AOTLinkedClassBulkLoader::load_classes_impl(LoaderKind loader_kind, Array<I
for (int i = 0; i < classes->length(); i++) {
InstanceKlass* ik = classes->at(i);
if (log_is_enabled(Info, cds, aot, load)) {
ResourceMark rm;
ResourceMark rm(THREAD);
log_info(cds, aot, load)("%s %s%s%s", category, ik->external_name(),
ik->is_loaded() ? " (already loaded)" : "",
ik->is_hidden() ? " (hidden)" : "");
@@ -159,7 +162,7 @@ void AOTLinkedClassBulkLoader::load_classes_impl(LoaderKind loader_kind, Array<I
}

if (actual != ik) {
ResourceMark rm;
ResourceMark rm(THREAD);
log_error(cds)("Unable to resolve %s class from CDS archive: %s", category, ik->external_name());
log_error(cds)("Expected: " INTPTR_FORMAT ", actual: " INTPTR_FORMAT, p2i(ik), p2i(actual));
log_error(cds)("JVMTI class retransformation is not supported when archive was generated with -XX:+AOTClassLinking.");
@@ -193,7 +196,7 @@ void AOTLinkedClassBulkLoader::initiate_loading(JavaThread* current, const char*
assert(ik->is_loaded(), "must have already been loaded by a parent loader");
if (ik->is_public() && !ik->is_hidden()) {
if (log_is_enabled(Info, cds, aot, load)) {
ResourceMark rm;
ResourceMark rm(current);
const char* defining_loader = (ik->class_loader() == nullptr ? "boot" : "plat");
log_info(cds, aot, load)("%s %s (initiated, defined by %s)", category, ik->external_name(),
defining_loader);
1 change: 1 addition & 0 deletions src/hotspot/share/cds/aotLinkedClassBulkLoader.hpp
Original file line number Diff line number Diff line change
@@ -50,6 +50,7 @@ class AOTLinkedClassBulkLoader : AllStatic {
};

static void load_classes_in_loader(JavaThread* current, LoaderKind loader_kind, oop class_loader_oop);
static void load_classes_in_loader_impl(LoaderKind loader_kind, oop class_loader_oop, TRAPS);
static void load_table(AOTLinkedClassTable* table, LoaderKind loader_kind, Handle loader, TRAPS);
static void initiate_loading(JavaThread* current, const char* category, Handle loader, Array<InstanceKlass*>* classes);
static void load_classes_impl(LoaderKind loader_kind, Array<InstanceKlass*>* classes, const char* category, Handle loader, TRAPS);
6 changes: 3 additions & 3 deletions src/hotspot/share/cds/archiveBuilder.cpp
Original file line number Diff line number Diff line change
@@ -907,9 +907,9 @@ void ArchiveBuilder::make_klasses_shareable() {
log_info(cds)(" unregistered " STATS_FORMAT, STATS_PARAMS(unregistered_klasses));
log_info(cds)(" (hidden) " STATS_FORMAT, STATS_PARAMS(hidden_klasses));
log_info(cds)(" (unlinked) " STATS_FORMAT ", boot = %d, plat = %d, app = %d, unreg = %d",
STATS_PARAMS(unlinked_klasses),
boot_unlinked, platform_unlinked,
app_unlinked, unreg_unlinked);
STATS_PARAMS(unlinked_klasses),
boot_unlinked, platform_unlinked,
app_unlinked, unreg_unlinked);
log_info(cds)(" obj array classes = %5d", num_obj_array_klasses);
log_info(cds)(" type array classes = %5d", num_type_array_klasses);
log_info(cds)(" symbols = %5d", _symbols->length());
7 changes: 6 additions & 1 deletion src/hotspot/share/cds/filemap.cpp
Original file line number Diff line number Diff line change
@@ -2044,7 +2044,7 @@ void FileMapInfo::map_or_load_heap_region() {

if (!success) {
if (CDSConfig::is_using_aot_linked_classes()) {
// It's too later to recover -- we have already committed to use the archived metaspace objects, but
// It's too late to recover -- we have already committed to use the archived metaspace objects, but
// the archived heap objects cannot be loaded, so we don't have the archived FMG to guarantee that
// all AOT-linked classes are visible.
//
@@ -2452,6 +2452,11 @@ bool FileMapHeader::validate() {
// header data
const char* prop = Arguments::get_property("java.system.class.loader");
if (prop != nullptr) {
if (has_aot_linked_classes()) {
log_error(cds)("CDS archive has aot-linked classes. It cannot be used when the "
"java.system.class.loader property is specified.");
return false;
}
log_warning(cds)("Archived non-system classes are disabled because the "
"java.system.class.loader property is specified (value = \"%s\"). "
"To use archived non-system classes, this property must not be set", prop);
2 changes: 1 addition & 1 deletion src/hotspot/share/cds/lambdaFormInvokers.cpp
Original file line number Diff line number Diff line change
@@ -101,7 +101,7 @@ void LambdaFormInvokers::regenerate_holder_classes(TRAPS) {
// The base archive may have some pre-resolved CP entries that point to the lambda form holder
// classes in the base archive. If we generate new versions of these classes, those CP entries
// will be pointing to invalid classes.
log_info(cds)("Base archive already have aot-linked lambda form holder classes. Cannot regenerate.");
log_info(cds)("Base archive already has aot-linked lambda form holder classes. Cannot regenerate.");
return;
}

Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2024, 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
@@ -57,6 +57,11 @@ public static void main(String[] args) throws Exception {
.assertAbnormalExit("CDS archive has aot-linked classes." +
" It cannot be used when archived full module graph is not used");

testCase("Cannot use -Djava.system.class.loader");
TestCommon.run("-cp", appJar, "-Djava.system.class.loader=dummy", "Hello")
.assertAbnormalExit("CDS archive has aot-linked classes." +
" It cannot be used when the java.system.class.loader property is specified.");

// NOTE: tests for ClassFileLoadHook + AOTClassLinking is in
// ../jvmti/ClassFileLoadHookTest.java
}