8024667: VM crashes with "assert(method() != NULL) failed: must have set method"
Summary: Check if data is in shared spaces before deallocating it.
Reviewed-by: coleenp, dcubed
--- a/hotspot/src/share/vm/memory/metadataFactory.hpp Sat Oct 12 13:09:18 2013 -0400
+++ b/hotspot/src/share/vm/memory/metadataFactory.hpp Sat Oct 12 15:39:16 2013 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2013, 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
@@ -65,6 +65,7 @@
static void free_array(ClassLoaderData* loader_data, Array<T>* data) {
if (data != NULL) {
assert(loader_data != NULL, "shouldn't pass null");
+ assert(!data->is_shared(), "cannot deallocate array in shared spaces");
int size = data->size();
if (DumpSharedSpaces) {
loader_data->ro_metaspace()->deallocate((MetaWord*)data, size, false);
@@ -83,6 +84,7 @@
// Call metadata's deallocate function which will call deallocate fields
assert(!DumpSharedSpaces, "cannot deallocate metadata when dumping CDS archive");
assert(!md->on_stack(), "can't deallocate things on stack");
+ assert(!md->is_shared(), "cannot deallocate if in shared spaces");
md->deallocate_contents(loader_data);
loader_data->metaspace_non_null()->deallocate((MetaWord*)md, size, md->is_klass());
}
--- a/hotspot/src/share/vm/oops/instanceKlass.cpp Sat Oct 12 13:09:18 2013 -0400
+++ b/hotspot/src/share/vm/oops/instanceKlass.cpp Sat Oct 12 15:39:16 2013 -0400
@@ -320,7 +320,8 @@
void InstanceKlass::deallocate_methods(ClassLoaderData* loader_data,
Array<Method*>* methods) {
- if (methods != NULL && methods != Universe::the_empty_method_array()) {
+ if (methods != NULL && methods != Universe::the_empty_method_array() &&
+ !methods->is_shared()) {
for (int i = 0; i < methods->length(); i++) {
Method* method = methods->at(i);
if (method == NULL) continue; // maybe null if error processing
@@ -344,13 +345,14 @@
// check that the interfaces don't come from super class
Array<Klass*>* sti = (super_klass == NULL) ? NULL :
InstanceKlass::cast(super_klass)->transitive_interfaces();
- if (ti != sti) {
+ if (ti != sti && ti != NULL && !ti->is_shared()) {
MetadataFactory::free_array<Klass*>(loader_data, ti);
}
}
// local interfaces can be empty
- if (local_interfaces != Universe::the_empty_klass_array()) {
+ if (local_interfaces != Universe::the_empty_klass_array() &&
+ local_interfaces != NULL && !local_interfaces->is_shared()) {
MetadataFactory::free_array<Klass*>(loader_data, local_interfaces);
}
}
@@ -380,21 +382,25 @@
deallocate_methods(loader_data, methods());
set_methods(NULL);
- if (method_ordering() != Universe::the_empty_int_array()) {
+ if (method_ordering() != NULL &&
+ method_ordering() != Universe::the_empty_int_array() &&
+ !method_ordering()->is_shared()) {
MetadataFactory::free_array<int>(loader_data, method_ordering());
}
set_method_ordering(NULL);
// default methods can be empty
if (default_methods() != NULL &&
- default_methods() != Universe::the_empty_method_array()) {
+ default_methods() != Universe::the_empty_method_array() &&
+ !default_methods()->is_shared()) {
MetadataFactory::free_array<Method*>(loader_data, default_methods());
}
// Do NOT deallocate the default methods, they are owned by superinterfaces.
set_default_methods(NULL);
// default methods vtable indices can be empty
- if (default_vtable_indices() != NULL) {
+ if (default_vtable_indices() != NULL &&
+ !default_vtable_indices()->is_shared()) {
MetadataFactory::free_array<int>(loader_data, default_vtable_indices());
}
set_default_vtable_indices(NULL);
@@ -403,8 +409,10 @@
// This array is in Klass, but remove it with the InstanceKlass since
// this place would be the only caller and it can share memory with transitive
// interfaces.
- if (secondary_supers() != Universe::the_empty_klass_array() &&
- secondary_supers() != transitive_interfaces()) {
+ if (secondary_supers() != NULL &&
+ secondary_supers() != Universe::the_empty_klass_array() &&
+ secondary_supers() != transitive_interfaces() &&
+ !secondary_supers()->is_shared()) {
MetadataFactory::free_array<Klass*>(loader_data, secondary_supers());
}
set_secondary_supers(NULL);
@@ -413,24 +421,32 @@
set_transitive_interfaces(NULL);
set_local_interfaces(NULL);
- MetadataFactory::free_array<jushort>(loader_data, fields());
+ if (fields() != NULL && !fields()->is_shared()) {
+ MetadataFactory::free_array<jushort>(loader_data, fields());
+ }
set_fields(NULL, 0);
// If a method from a redefined class is using this constant pool, don't
// delete it, yet. The new class's previous version will point to this.
if (constants() != NULL) {
assert (!constants()->on_stack(), "shouldn't be called if anything is onstack");
- MetadataFactory::free_metadata(loader_data, constants());
+ if (!constants()->is_shared()) {
+ MetadataFactory::free_metadata(loader_data, constants());
+ }
set_constants(NULL);
}
- if (inner_classes() != Universe::the_empty_short_array()) {
+ if (inner_classes() != NULL &&
+ inner_classes() != Universe::the_empty_short_array() &&
+ !inner_classes()->is_shared()) {
MetadataFactory::free_array<jushort>(loader_data, inner_classes());
}
set_inner_classes(NULL);
- // We should deallocate the Annotations instance
- MetadataFactory::free_metadata(loader_data, annotations());
+ // We should deallocate the Annotations instance if it's not in shared spaces.
+ if (annotations() != NULL && !annotations()->is_shared()) {
+ MetadataFactory::free_metadata(loader_data, annotations());
+ }
set_annotations(NULL);
}