Skip to content

Commit 27b0f77

Browse files
committed
8292318: Memory corruption in remove_dumptime_info
Reviewed-by: coleenp, ccheung
1 parent 9a65524 commit 27b0f77

File tree

7 files changed

+39
-85
lines changed

7 files changed

+39
-85
lines changed

src/hotspot/share/classfile/systemDictionaryShared.cpp

-37
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,6 @@ DumpTimeSharedClassTable* SystemDictionaryShared::_dumptime_table = NULL;
8080
DumpTimeSharedClassTable* SystemDictionaryShared::_cloned_dumptime_table = NULL;
8181
DumpTimeLambdaProxyClassDictionary* SystemDictionaryShared::_dumptime_lambda_proxy_class_dictionary = NULL;
8282
DumpTimeLambdaProxyClassDictionary* SystemDictionaryShared::_cloned_dumptime_lambda_proxy_class_dictionary = NULL;
83-
SystemDictionaryShared::SavedCpCacheEntriesTable* SystemDictionaryShared::_saved_cpcache_entries_table = NULL;
8483

8584
// Used by NoClassLoadingMark
8685
DEBUG_ONLY(bool SystemDictionaryShared::_class_loading_may_happen = true;)
@@ -505,7 +504,6 @@ void SystemDictionaryShared::initialize() {
505504
_dumptime_table = new (ResourceObj::C_HEAP, mtClass) DumpTimeSharedClassTable;
506505
_dumptime_lambda_proxy_class_dictionary =
507506
new (ResourceObj::C_HEAP, mtClass) DumpTimeLambdaProxyClassDictionary;
508-
_saved_cpcache_entries_table = new (ResourceObj::C_HEAP, mtClass) SavedCpCacheEntriesTable;
509507
}
510508
}
511509

@@ -518,11 +516,6 @@ void SystemDictionaryShared::init_dumptime_info(InstanceKlass* k) {
518516
void SystemDictionaryShared::remove_dumptime_info(InstanceKlass* k) {
519517
MutexLocker ml(DumpTimeTable_lock, Mutex::_no_safepoint_check_flag);
520518
_dumptime_table->remove(k);
521-
522-
ConstantPoolCache* cpc = k->constants()->cache();
523-
if (cpc != NULL) {
524-
remove_saved_cpcache_entries_locked(cpc);
525-
}
526519
}
527520

528521
void SystemDictionaryShared::handle_class_unloading(InstanceKlass* klass) {
@@ -1336,36 +1329,6 @@ void SystemDictionaryShared::update_shared_entry(InstanceKlass* k, int id) {
13361329
info->_id = id;
13371330
}
13381331

1339-
void SystemDictionaryShared::set_saved_cpcache_entries(ConstantPoolCache* cpc, ConstantPoolCacheEntry* entries) {
1340-
MutexLocker ml(DumpTimeTable_lock, Mutex::_no_safepoint_check_flag);
1341-
bool is_new = _saved_cpcache_entries_table->put(cpc, entries);
1342-
assert(is_new, "saved entries must never changed");
1343-
}
1344-
1345-
ConstantPoolCacheEntry* SystemDictionaryShared::get_saved_cpcache_entries_locked(ConstantPoolCache* cpc) {
1346-
assert_lock_strong(DumpTimeTable_lock);
1347-
ConstantPoolCacheEntry** p = _saved_cpcache_entries_table->get(cpc);
1348-
if (p != nullptr) {
1349-
return *p;
1350-
} else {
1351-
return nullptr;
1352-
}
1353-
}
1354-
1355-
void SystemDictionaryShared::remove_saved_cpcache_entries(ConstantPoolCache* cpc) {
1356-
MutexLocker ml(DumpTimeTable_lock, Mutex::_no_safepoint_check_flag);
1357-
remove_saved_cpcache_entries_locked(cpc);
1358-
}
1359-
1360-
void SystemDictionaryShared::remove_saved_cpcache_entries_locked(ConstantPoolCache* cpc) {
1361-
assert_lock_strong(DumpTimeTable_lock);
1362-
ConstantPoolCacheEntry** p = _saved_cpcache_entries_table->get(cpc);
1363-
if (p != nullptr) {
1364-
_saved_cpcache_entries_table->remove(cpc);
1365-
FREE_C_HEAP_ARRAY(ConstantPoolCacheEntry, *p);
1366-
}
1367-
}
1368-
13691332
const char* class_loader_name_for_shared(Klass* k) {
13701333
assert(k != nullptr, "Sanity");
13711334
assert(k->is_shared(), "Must be");

src/hotspot/share/classfile/systemDictionaryShared.hpp

-14
Original file line numberDiff line numberDiff line change
@@ -168,15 +168,6 @@ class SystemDictionaryShared: public SystemDictionary {
168168
static DumpTimeLambdaProxyClassDictionary* _dumptime_lambda_proxy_class_dictionary;
169169
static DumpTimeLambdaProxyClassDictionary* _cloned_dumptime_lambda_proxy_class_dictionary;
170170

171-
// Doesn't need to be cloned as it's not modified during dump time.
172-
using SavedCpCacheEntriesTable = ResourceHashtable<
173-
ConstantPoolCache*,
174-
ConstantPoolCacheEntry*,
175-
15889, // prime number
176-
ResourceObj::C_HEAP,
177-
mtClassShared>;
178-
static SavedCpCacheEntriesTable* _saved_cpcache_entries_table;
179-
180171
static ArchiveInfo _static_archive;
181172
static ArchiveInfo _dynamic_archive;
182173

@@ -248,11 +239,6 @@ class SystemDictionaryShared: public SystemDictionary {
248239
return ClassLoaderData::the_null_class_loader_data()->dictionary();
249240
}
250241

251-
static void set_saved_cpcache_entries(ConstantPoolCache* cpc, ConstantPoolCacheEntry* entries);
252-
static ConstantPoolCacheEntry* get_saved_cpcache_entries_locked(ConstantPoolCache* k);
253-
static void remove_saved_cpcache_entries(ConstantPoolCache* cpc);
254-
static void remove_saved_cpcache_entries_locked(ConstantPoolCache* cpc);
255-
256242
static void update_shared_entry(InstanceKlass* klass, int id);
257243
static void set_shared_class_misc_info(InstanceKlass* k, ClassFileStream* cfs);
258244

src/hotspot/share/interpreter/rewriter.cpp

+11-11
Original file line numberDiff line numberDiff line change
@@ -112,21 +112,21 @@ void Rewriter::make_constant_pool_cache(TRAPS) {
112112
_resolved_reference_limit,
113113
THREAD);
114114

115+
if (!HAS_PENDING_EXCEPTION && Arguments::is_dumping_archive()) {
116+
if (_pool->pool_holder()->is_shared()) {
117+
assert(DynamicDumpSharedSpaces, "must be");
118+
// We are linking a shared class from the base archive. This
119+
// class won't be written into the dynamic archive, so there's no
120+
// need to save its CpCaches.
121+
} else {
122+
cache->save_for_archive(THREAD);
123+
}
124+
}
125+
115126
// Clean up constant pool cache if initialize_resolved_references() failed.
116127
if (HAS_PENDING_EXCEPTION) {
117128
MetadataFactory::free_metadata(loader_data, cache);
118129
_pool->set_cache(NULL); // so the verifier isn't confused
119-
} else {
120-
if (Arguments::is_dumping_archive()) {
121-
if (_pool->pool_holder()->is_shared()) {
122-
assert(DynamicDumpSharedSpaces, "must be");
123-
// We are linking a shared class from the base archive. This
124-
// class won't be written into the dynamic archive, so there's no
125-
// need to save its CpCaches.
126-
} else {
127-
cache->save_for_archive();
128-
}
129-
}
130130
}
131131
}
132132

src/hotspot/share/oops/cpCache.cpp

+16-14
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
*/
2424

2525
#include "precompiled.hpp"
26+
#include "cds/archiveBuilder.hpp"
2627
#include "cds/heapShared.hpp"
2728
#include "classfile/resolutionErrors.hpp"
2829
#include "classfile/systemDictionary.hpp"
@@ -683,30 +684,30 @@ void ConstantPoolCache::record_gc_epoch() {
683684
_gc_epoch = Continuations::gc_epoch();
684685
}
685686

686-
void ConstantPoolCache::save_for_archive() {
687+
void ConstantPoolCache::save_for_archive(TRAPS) {
687688
#if INCLUDE_CDS
688-
ConstantPoolCacheEntry* copy = NEW_C_HEAP_ARRAY(ConstantPoolCacheEntry, length(), mtClassShared);
689+
ClassLoaderData* loader_data = constant_pool()->pool_holder()->class_loader_data();
690+
_initial_entries = MetadataFactory::new_array<ConstantPoolCacheEntry>(loader_data, length(), CHECK);
689691
for (int i = 0; i < length(); i++) {
690-
copy[i] = *entry_at(i);
692+
_initial_entries->at_put(i, *entry_at(i));
691693
}
692-
693-
SystemDictionaryShared::set_saved_cpcache_entries(this, copy);
694694
#endif
695695
}
696696

697697
void ConstantPoolCache::remove_unshareable_info() {
698698
#if INCLUDE_CDS
699699
Arguments::assert_is_dumping_archive();
700-
// <this> is the copy to be written into the archive. It's in
701-
// the ArchiveBuilder's "buffer space". However, the saved_cpcache_entries
702-
// are recorded with the original ConstantPoolCache object.
703-
ConstantPoolCache* orig_cpc = ArchiveBuilder::current()->get_src_obj(this);
704-
ConstantPoolCacheEntry* saved = SystemDictionaryShared::get_saved_cpcache_entries_locked(orig_cpc);
700+
// <this> is the copy to be written into the archive. It's in the ArchiveBuilder's "buffer space".
701+
// However, this->_initial_entries was not copied/relocated by the ArchiveBuilder, so it's
702+
// still pointing to the array allocated inside save_for_archive().
703+
assert(_initial_entries != NULL, "archived cpcache must have been initialized");
704+
assert(!ArchiveBuilder::current()->is_in_buffer_space(_initial_entries), "must be");
705705
for (int i=0; i<length(); i++) {
706706
// Restore each entry to the initial state -- just after Rewriter::make_constant_pool_cache()
707707
// has finished.
708-
*entry_at(i) = saved[i];
708+
*entry_at(i) = _initial_entries->at(i);
709709
}
710+
_initial_entries = NULL;
710711
#endif
711712
}
712713

@@ -716,10 +717,11 @@ void ConstantPoolCache::deallocate_contents(ClassLoaderData* data) {
716717
set_resolved_references(OopHandle());
717718
MetadataFactory::free_array<u2>(data, _reference_map);
718719
set_reference_map(NULL);
719-
720720
#if INCLUDE_CDS
721-
if (Arguments::is_dumping_archive()) {
722-
SystemDictionaryShared::remove_saved_cpcache_entries(this);
721+
if (_initial_entries != NULL) {
722+
Arguments::assert_is_dumping_archive();
723+
MetadataFactory::free_array<ConstantPoolCacheEntry>(data, _initial_entries);
724+
_initial_entries = NULL;
723725
}
724726
#endif
725727
}

src/hotspot/share/oops/cpCache.hpp

+7-4
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,11 @@ class ConstantPoolCache: public MetaspaceObj {
401401
// If you add a new field that points to any metaspace object, you
402402
// must add this field to ConstantPoolCache::metaspace_pointers_do().
403403
int _length;
404+
405+
// The narrowOop pointer to the archived resolved_references. Set at CDS dump
406+
// time when caching java heap object is supported.
407+
CDS_JAVA_HEAP_ONLY(int _archived_references_index;) // Gap on LP64
408+
404409
ConstantPool* _constant_pool; // the corresponding constant pool
405410

406411
// The following fields need to be modified at runtime, so they cannot be
@@ -413,9 +418,7 @@ class ConstantPoolCache: public MetaspaceObj {
413418
// RedefineClasses support
414419
uint64_t _gc_epoch;
415420

416-
// The narrowOop pointer to the archived resolved_references. Set at CDS dump
417-
// time when caching java heap object is supported.
418-
CDS_JAVA_HEAP_ONLY(int _archived_references_index;)
421+
CDS_ONLY(Array<ConstantPoolCacheEntry>* _initial_entries;)
419422

420423
// Sizing
421424
debug_only(friend class ClassVerifier;)
@@ -454,7 +457,7 @@ class ConstantPoolCache: public MetaspaceObj {
454457

455458
// CDS support
456459
void remove_unshareable_info();
457-
void save_for_archive();
460+
void save_for_archive(TRAPS);
458461
private:
459462
void walk_entries_for_initialization(bool check_only);
460463
void set_length(int length) { _length = length; }

src/hotspot/share/oops/instanceKlass.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -576,8 +576,6 @@ void InstanceKlass::deallocate_record_components(ClassLoaderData* loader_data,
576576
// This function deallocates the metadata and C heap pointers that the
577577
// InstanceKlass points to.
578578
void InstanceKlass::deallocate_contents(ClassLoaderData* loader_data) {
579-
SystemDictionaryShared::handle_class_unloading(this);
580-
581579
// Orphan the mirror first, CMS thinks it's still live.
582580
if (java_mirror() != NULL) {
583581
java_lang_Class::set_klass(java_mirror(), NULL);
@@ -692,6 +690,8 @@ void InstanceKlass::deallocate_contents(ClassLoaderData* loader_data) {
692690
MetadataFactory::free_metadata(loader_data, annotations());
693691
}
694692
set_annotations(NULL);
693+
694+
SystemDictionaryShared::handle_class_unloading(this);
695695
}
696696

697697
bool InstanceKlass::is_record() const {

test/hotspot/jtreg/runtime/cds/MaxMetaspaceSize.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -51,8 +51,8 @@ public static void main(String[] args) throws Exception {
5151
processArgs.add("-XX:MaxMetaspaceSize=1m");
5252
}
5353

54-
String msg = "OutOfMemoryError: Metaspace";
54+
String msg = "OutOfMemoryError: ((Metaspace)|(Compressed class space))";
5555
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(processArgs);
56-
CDSTestUtils.executeAndLog(pb, "dump").shouldContain(msg).shouldHaveExitValue(1);
56+
CDSTestUtils.executeAndLog(pb, "dump").shouldMatch(msg).shouldHaveExitValue(1);
5757
}
5858
}

0 commit comments

Comments
 (0)