mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 15:24:43 +02:00
8010319: Implementation of JEP 181: Nest-Based Access Control
Co-authored-by: Alex Buckley <alex.buckley@oracle.com> Co-authored-by: Maurizio Mimadamore <maurizio.mimadamore@oracle.com> Co-authored-by: Mandy Chung <mandy.chung@oracle.com> Co-authored-by: Tobias Hartmann <tobias.hartmann@oracle.com> Co-authored-by: Vlaidmir Ivanov <vladimir.x.ivanov@oracle.com> Co-authored-by: Karen Kinnear <karen.kinnear@oracle.com> Co-authored-by: Vladimir Kozlov <vladimir.kozlov@oracle.com> Co-authored-by: John Rose <john.r.rose@oracle.com> Co-authored-by: Daniel Smith <daniel.smith@oracle.com> Co-authored-by: Serguei Spitsyn <serguei.spitsyn@oracle.com> Co-authored-by: Kumar Srinivasan <kumardotsrinivasan@gmail.com> Co-authored-by: Boris Ulasevich <boris.ulasevich@bell-sw.com> Reviewed-by: alanb, psandoz, mchung, coleenp, acorn, mcimadamore, forax, jlahoda, sspitsyn, abuckley
This commit is contained in:
parent
6e0bd36f42
commit
95bf19563b
259 changed files with 21354 additions and 890 deletions
|
@ -683,6 +683,95 @@ void VM_RedefineClasses::finalize_operands_merge(const constantPoolHandle& merge
|
|||
_operands_index_map_count = 0;
|
||||
} // end finalize_operands_merge()
|
||||
|
||||
// Symbol* comparator for qsort
|
||||
// The caller must have an active ResourceMark.
|
||||
static int symcmp(const void* a, const void* b) {
|
||||
char* astr = (*(Symbol**)a)->as_C_string();
|
||||
char* bstr = (*(Symbol**)b)->as_C_string();
|
||||
return strcmp(astr, bstr);
|
||||
}
|
||||
|
||||
static jvmtiError check_nest_attributes(InstanceKlass* the_class,
|
||||
InstanceKlass* scratch_class) {
|
||||
// Check whether the class NestHost attribute has been changed.
|
||||
Thread* thread = Thread::current();
|
||||
ResourceMark rm(thread);
|
||||
JvmtiThreadState *state = JvmtiThreadState::state_for((JavaThread*)thread);
|
||||
u2 the_nest_host_idx = the_class->nest_host_index();
|
||||
u2 scr_nest_host_idx = scratch_class->nest_host_index();
|
||||
|
||||
if (the_nest_host_idx != 0 && scr_nest_host_idx != 0) {
|
||||
Symbol* the_sym = the_class->constants()->klass_name_at(the_nest_host_idx);
|
||||
Symbol* scr_sym = scratch_class->constants()->klass_name_at(scr_nest_host_idx);
|
||||
if (the_sym != scr_sym) {
|
||||
log_trace(redefine, class, nestmates)
|
||||
("redefined class %s attribute change error: NestHost class: %s replaced with: %s",
|
||||
the_class->external_name(), the_sym->as_C_string(), scr_sym->as_C_string());
|
||||
return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_ATTRIBUTE_CHANGED;
|
||||
}
|
||||
} else if ((the_nest_host_idx == 0) ^ (scr_nest_host_idx == 0)) {
|
||||
const char* action_str = (the_nest_host_idx != 0) ? "removed" : "added";
|
||||
log_trace(redefine, class, nestmates)
|
||||
("redefined class %s attribute change error: NestHost attribute %s",
|
||||
the_class->external_name(), action_str);
|
||||
return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_ATTRIBUTE_CHANGED;
|
||||
}
|
||||
|
||||
// Check whether the class NestMembers attribute has been changed.
|
||||
Array<u2>* the_nest_members = the_class->nest_members();
|
||||
Array<u2>* scr_nest_members = scratch_class->nest_members();
|
||||
bool the_members_exists = the_nest_members != Universe::the_empty_short_array();
|
||||
bool scr_members_exists = scr_nest_members != Universe::the_empty_short_array();
|
||||
|
||||
int members_len = the_nest_members->length();
|
||||
if (the_members_exists && scr_members_exists) {
|
||||
if (members_len != scr_nest_members->length()) {
|
||||
log_trace(redefine, class, nestmates)
|
||||
("redefined class %s attribute change error: NestMember len=%d changed to len=%d",
|
||||
the_class->external_name(), members_len, scr_nest_members->length());
|
||||
return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_ATTRIBUTE_CHANGED;
|
||||
}
|
||||
|
||||
// The order of entries in the NestMembers array is not specified so we
|
||||
// have to explicitly check for the same contents. We do this by copying
|
||||
// the referenced symbols into their own arrays, sorting them and then
|
||||
// comparing each element pair.
|
||||
|
||||
Symbol** the_syms = NEW_RESOURCE_ARRAY_RETURN_NULL(Symbol*, members_len);
|
||||
Symbol** scr_syms = NEW_RESOURCE_ARRAY_RETURN_NULL(Symbol*, members_len);
|
||||
|
||||
if (the_syms == NULL || scr_syms == NULL) {
|
||||
return JVMTI_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
for (int i = 0; i < members_len; i++) {
|
||||
int the_cp_index = the_nest_members->at(i);
|
||||
int scr_cp_index = scr_nest_members->at(i);
|
||||
the_syms[i] = the_class->constants()->klass_name_at(the_cp_index);
|
||||
scr_syms[i] = scratch_class->constants()->klass_name_at(scr_cp_index);
|
||||
}
|
||||
|
||||
qsort(the_syms, members_len, sizeof(Symbol*), symcmp);
|
||||
qsort(scr_syms, members_len, sizeof(Symbol*), symcmp);
|
||||
|
||||
for (int i = 0; i < members_len; i++) {
|
||||
if (the_syms[i] != scr_syms[i]) {
|
||||
log_trace(redefine, class, nestmates)
|
||||
("redefined class %s attribute change error: NestMembers[%d]: %s changed to %s",
|
||||
the_class->external_name(), i, the_syms[i]->as_C_string(), scr_syms[i]->as_C_string());
|
||||
return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_ATTRIBUTE_CHANGED;
|
||||
}
|
||||
}
|
||||
} else if (the_members_exists ^ scr_members_exists) {
|
||||
const char* action_str = (the_members_exists) ? "removed" : "added";
|
||||
log_trace(redefine, class, nestmates)
|
||||
("redefined class %s attribute change error: NestMembers attribute %s",
|
||||
the_class->external_name(), action_str);
|
||||
return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_ATTRIBUTE_CHANGED;
|
||||
}
|
||||
|
||||
return JVMTI_ERROR_NONE;
|
||||
}
|
||||
|
||||
jvmtiError VM_RedefineClasses::compare_and_normalize_class_versions(
|
||||
InstanceKlass* the_class,
|
||||
|
@ -725,6 +814,12 @@ jvmtiError VM_RedefineClasses::compare_and_normalize_class_versions(
|
|||
return JVMTI_ERROR_INVALID_CLASS;
|
||||
}
|
||||
|
||||
// Check whether the nest-related attributes have been changed.
|
||||
jvmtiError err = check_nest_attributes(the_class, scratch_class);
|
||||
if (err != JVMTI_ERROR_NONE) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// Check whether class modifiers are the same.
|
||||
jushort old_flags = (jushort) the_class->access_flags().get_flags();
|
||||
jushort new_flags = (jushort) scratch_class->access_flags().get_flags();
|
||||
|
@ -1598,6 +1693,12 @@ jvmtiError VM_RedefineClasses::merge_cp_and_rewrite(
|
|||
bool VM_RedefineClasses::rewrite_cp_refs(InstanceKlass* scratch_class,
|
||||
TRAPS) {
|
||||
|
||||
// rewrite constant pool references in the nest attributes:
|
||||
if (!rewrite_cp_refs_in_nest_attributes(scratch_class)) {
|
||||
// propagate failure back to caller
|
||||
return false;
|
||||
}
|
||||
|
||||
// rewrite constant pool references in the methods:
|
||||
if (!rewrite_cp_refs_in_methods(scratch_class, THREAD)) {
|
||||
// propagate failure back to caller
|
||||
|
@ -1680,6 +1781,22 @@ bool VM_RedefineClasses::rewrite_cp_refs(InstanceKlass* scratch_class,
|
|||
return true;
|
||||
} // end rewrite_cp_refs()
|
||||
|
||||
// Rewrite constant pool references in the NestHost and NestMembers attributes.
|
||||
bool VM_RedefineClasses::rewrite_cp_refs_in_nest_attributes(
|
||||
InstanceKlass* scratch_class) {
|
||||
|
||||
u2 cp_index = scratch_class->nest_host_index();
|
||||
if (cp_index != 0) {
|
||||
scratch_class->set_nest_host_index(find_new_index(cp_index));
|
||||
}
|
||||
Array<u2>* nest_members = scratch_class->nest_members();
|
||||
for (int i = 0; i < nest_members->length(); i++) {
|
||||
u2 cp_index = nest_members->at(i);
|
||||
nest_members->at_put(i, find_new_index(cp_index));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Rewrite constant pool references in the methods.
|
||||
bool VM_RedefineClasses::rewrite_cp_refs_in_methods(
|
||||
InstanceKlass* scratch_class, TRAPS) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue