8284435: Add dedicated filler objects for known dead Java heap areas

Reviewed-by: iklam, iwalulya
This commit is contained in:
Thomas Schatzl 2022-05-02 11:03:57 +00:00
parent 1f9f8738f3
commit 7020595631
8 changed files with 111 additions and 2 deletions
src
hotspot/share
java.base/share/classes/jdk/internal/vm
test/hotspot/jtreg/gc

@ -1717,5 +1717,6 @@ void SystemDictionaryShared::update_archived_mirror_native_pointers() {
Klass* k = Universe::typeArrayKlassObj((BasicType)t);
ArchivedMirrorPatcher::update_array_klasses(k);
}
ArchivedMirrorPatcher::update_array_klasses(Universe::fillerArrayKlassObj());
}
#endif

@ -183,6 +183,9 @@
do_klass(vector_VectorMask_klass, jdk_internal_vm_vector_VectorMask ) \
do_klass(vector_VectorShuffle_klass, jdk_internal_vm_vector_VectorShuffle ) \
\
/* GC support */ \
do_klass(FillerObject_klass, jdk_internal_vm_FillerObject ) \
\
/*end*/
#endif // SHARE_CLASSFILE_VMCLASSMACROS_HPP

@ -91,6 +91,8 @@
template(ETYPE_name, "ETYPE") \
template(VLENGTH_name, "VLENGTH") \
\
template(jdk_internal_vm_FillerObject, "jdk/internal/vm/FillerObject") \
\
template(java_lang_Shutdown, "java/lang/Shutdown") \
template(java_lang_ref_Reference, "java/lang/ref/Reference") \
template(java_lang_ref_SoftReference, "java/lang/ref/SoftReference") \

@ -447,7 +447,7 @@ CollectedHeap::fill_with_array(HeapWord* start, size_t words, bool zap)
const size_t len = payload_size * HeapWordSize / sizeof(jint);
assert((int)len >= 0, "size too large " SIZE_FORMAT " becomes %d", words, (int)len);
ObjArrayAllocator allocator(Universe::intArrayKlassObj(), words, (int)len, /* do_zero */ false);
ObjArrayAllocator allocator(Universe::fillerArrayKlassObj(), words, (int)len, /* do_zero */ false);
allocator.initialize(start);
if (DumpSharedSpaces) {
// This array is written into the CDS archive. Make sure it
@ -467,7 +467,7 @@ CollectedHeap::fill_with_object_impl(HeapWord* start, size_t words, bool zap)
fill_with_array(start, words, zap);
} else if (words > 0) {
assert(words == min_fill_size(), "unaligned size");
ObjAllocator allocator(vmClasses::Object_klass(), words);
ObjAllocator allocator(vmClasses::FillerObject_klass(), words);
allocator.initialize(start);
}
}

@ -84,6 +84,7 @@
// Known objects
Klass* Universe::_typeArrayKlassObjs[T_LONG+1] = { NULL /*, NULL...*/ };
Klass* Universe::_objectArrayKlassObj = NULL;
Klass* Universe::_fillerArrayKlassObj = NULL;
OopHandle Universe::_mirrors[T_VOID+1];
OopHandle Universe::_main_thread_group;
@ -200,6 +201,11 @@ void Universe::basic_type_classes_do(KlassClosure *closure) {
for (int i = T_BOOLEAN; i < T_LONG+1; i++) {
closure->do_klass(_typeArrayKlassObjs[i]);
}
// We don't do the following because it will confuse JVMTI.
// _fillerArrayKlassObj is used only by GC, which doesn't need to see
// this klass from basic_type_classes_do().
//
// closure->do_klass(_fillerArrayKlassObj);
}
void LatestMethodCache::metaspace_pointers_do(MetaspaceClosure* it) {
@ -207,6 +213,7 @@ void LatestMethodCache::metaspace_pointers_do(MetaspaceClosure* it) {
}
void Universe::metaspace_pointers_do(MetaspaceClosure* it) {
it->push(&_fillerArrayKlassObj);
for (int i = 0; i < T_LONG+1; i++) {
it->push(&_typeArrayKlassObjs[i]);
}
@ -255,6 +262,7 @@ void Universe::serialize(SerializeClosure* f) {
}
#endif
f->do_ptr((void**)&_fillerArrayKlassObj);
for (int i = 0; i < T_LONG+1; i++) {
f->do_ptr((void**)&_typeArrayKlassObjs[i]);
}
@ -314,6 +322,10 @@ void Universe::genesis(TRAPS) {
compute_base_vtable_size();
if (!UseSharedSpaces) {
// Initialization of the fillerArrayKlass must come before regular
// int-TypeArrayKlass so that the int-Array mirror points to the
// int-TypeArrayKlass.
_fillerArrayKlassObj = TypeArrayKlass::create_klass(T_INT, "Ljava/internal/vm/FillerArray;", CHECK);
for (int i = T_BOOLEAN; i < T_LONG+1; i++) {
_typeArrayKlassObjs[i] = TypeArrayKlass::create_klass((BasicType)i, CHECK);
}
@ -355,6 +367,8 @@ void Universe::genesis(TRAPS) {
_the_array_interfaces_array->at_put(1, vmClasses::Serializable_klass());
}
initialize_basic_type_klass(_fillerArrayKlassObj, CHECK);
initialize_basic_type_klass(boolArrayKlassObj(), CHECK);
initialize_basic_type_klass(charArrayKlassObj(), CHECK);
initialize_basic_type_klass(floatArrayKlassObj(), CHECK);
@ -363,6 +377,9 @@ void Universe::genesis(TRAPS) {
initialize_basic_type_klass(shortArrayKlassObj(), CHECK);
initialize_basic_type_klass(intArrayKlassObj(), CHECK);
initialize_basic_type_klass(longArrayKlassObj(), CHECK);
assert(_fillerArrayKlassObj != intArrayKlassObj(),
"Internal filler array klass should be different to int array Klass");
} // end of core bootstrapping
{

@ -95,6 +95,9 @@ class Universe: AllStatic {
// Known classes in the VM
static Klass* _typeArrayKlassObjs[T_LONG+1];
static Klass* _objectArrayKlassObj;
// Special int-Array that represents filler objects that are used by GC to overwrite
// dead objects. References to them are generally an error.
static Klass* _fillerArrayKlassObj;
// Known objects in the VM
static OopHandle _main_thread_group; // Reference to the main thread group object
@ -208,6 +211,8 @@ class Universe: AllStatic {
static Klass* objectArrayKlassObj() { return _objectArrayKlassObj; }
static Klass* fillerArrayKlassObj() { return _fillerArrayKlassObj; }
static Klass* typeArrayKlassObj(BasicType t) {
assert((uint)t >= T_BOOLEAN, "range check for type: %s", type2name(t));
assert((uint)t < T_LONG+1, "range check for type: %s", type2name(t));

@ -0,0 +1,31 @@
/*
* Copyright (c) 2021, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.internal.vm;
/*
* Support class used for filling small dead areas.
*/
class FillerObject {
}

@ -0,0 +1,50 @@
/*
* Copyright (c) 2022, 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.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package gc;
/*
* @test TestFillerObjectInstantiation
* @summary Test that GC filler objects can not be instantiated by Java programs.
* @library /test/lib
* @run driver gc.TestFillerObjectInstantiation
*/
public class TestFillerObjectInstantiation {
private static void testInstantiationFails(String classname) throws Exception {
System.out.println("trying to instantiate " + classname);
try {
Object o = ClassLoader.getSystemClassLoader().loadClass(classname).newInstance();
throw new Error("Have been able to instantiate " + classname);
} catch (IllegalAccessException | ClassNotFoundException e) {
System.out.println("Could not instantiate " + classname + " as expected");
System.out.println("Message: " + e.toString());
}
}
public static void main(String[] args) throws Exception {
testInstantiationFails("jdk.internal.vm.FillerObject");
testInstantiationFails("jdk.internal.vm.FillerArray");
}
}