This commit is contained in:
Henry Jen 2019-03-26 10:55:17 -07:00
commit 52da980fa2
4374 changed files with 112127 additions and 138806 deletions

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2019, 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
@ -52,7 +52,7 @@
#include "oops/klass.inline.hpp"
#include "oops/klassVtable.hpp"
#include "oops/metadata.hpp"
#include "oops/method.hpp"
#include "oops/method.inline.hpp"
#include "oops/oop.inline.hpp"
#include "oops/symbol.hpp"
#include "prims/jvmtiExport.hpp"
@ -60,6 +60,7 @@
#include "runtime/arguments.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/javaCalls.hpp"
#include "runtime/os.hpp"
#include "runtime/perfData.hpp"
#include "runtime/reflection.hpp"
#include "runtime/safepointVerifiers.hpp"
@ -564,7 +565,7 @@ void ClassFileParser::parse_constant_pool(const ClassFileStream* const stream,
}
case JVM_CONSTANT_Dynamic: {
const int name_and_type_ref_index =
cp->invoke_dynamic_name_and_type_ref_index_at(index);
cp->bootstrap_name_and_type_ref_index_at(index);
check_property(valid_cp_range(name_and_type_ref_index, length) &&
cp->tag_at(name_and_type_ref_index).is_name_and_type(),
@ -579,7 +580,7 @@ void ClassFileParser::parse_constant_pool(const ClassFileStream* const stream,
}
case JVM_CONSTANT_InvokeDynamic: {
const int name_and_type_ref_index =
cp->invoke_dynamic_name_and_type_ref_index_at(index);
cp->bootstrap_name_and_type_ref_index_at(index);
check_property(valid_cp_range(name_and_type_ref_index, length) &&
cp->tag_at(name_and_type_ref_index).is_name_and_type(),
@ -1973,46 +1974,6 @@ const ClassFileParser::unsafe_u2* ClassFileParser::parse_localvariable_table(con
return localvariable_table_start;
}
void ClassFileParser::parse_type_array(u2 array_length,
u4 code_length,
u4* const u1_index,
u4* const u2_index,
u1* const u1_array,
u2* const u2_array,
TRAPS) {
const ClassFileStream* const cfs = _stream;
u2 index = 0; // index in the array with long/double occupying two slots
u4 i1 = *u1_index;
u4 i2 = *u2_index + 1;
for(int i = 0; i < array_length; i++) {
const u1 tag = u1_array[i1++] = cfs->get_u1(CHECK);
index++;
if (tag == ITEM_Long || tag == ITEM_Double) {
index++;
} else if (tag == ITEM_Object) {
const u2 class_index = u2_array[i2++] = cfs->get_u2(CHECK);
guarantee_property(valid_klass_reference_at(class_index),
"Bad class index %u in StackMap in class file %s",
class_index, CHECK);
} else if (tag == ITEM_Uninitialized) {
const u2 offset = u2_array[i2++] = cfs->get_u2(CHECK);
guarantee_property(
offset < code_length,
"Bad uninitialized type offset %u in StackMap in class file %s",
offset, CHECK);
} else {
guarantee_property(
tag <= (u1)ITEM_Uninitialized,
"Unknown variable type %u in StackMap in class file %s",
tag, CHECK);
}
}
u2_array[*u2_index] = index;
*u1_index = i1;
*u2_index = i2;
}
static const u1* parse_stackmap_table(const ClassFileStream* const cfs,
u4 code_attribute_length,
bool need_verify,
@ -2120,12 +2081,7 @@ AnnotationCollector::annotation_index(const ClassLoaderData* loader_data,
if (!privileged) break; // only allow in privileged code
return _method_LambdaForm_Compiled;
}
case vmSymbols::VM_SYMBOL_ENUM_NAME(java_lang_invoke_LambdaForm_Hidden_signature): {
if (_location != _in_method) break; // only allow for methods
if (!privileged) break; // only allow in privileged code
return _method_Hidden;
}
case vmSymbols::VM_SYMBOL_ENUM_NAME(java_security_AccessController_Hidden_signature): {
case vmSymbols::VM_SYMBOL_ENUM_NAME(jdk_internal_vm_annotation_Hidden_signature): {
if (_location != _in_method) break; // only allow for methods
if (!privileged) break; // only allow in privileged code
return _method_Hidden;
@ -4996,42 +4952,43 @@ void ClassFileParser::verify_legal_utf8(const unsigned char* buffer,
bool ClassFileParser::verify_unqualified_name(const char* name,
unsigned int length,
int type) {
for (const char* p = name; p != name + length;) {
jchar ch = *p;
if (ch < 128) {
if (ch == '.' || ch == ';' || ch == '[' ) {
return false; // do not permit '.', ';', or '['
}
if (ch == '/') {
for (const char* p = name; p != name + length; p++) {
switch(*p) {
case '.':
case ';':
case '[':
// do not permit '.', ';', or '['
return false;
case '/':
// check for '//' or leading or trailing '/' which are not legal
// unqualified name must not be empty
if (type == ClassFileParser::LegalClass) {
if (p == name || p+1 >= name+length || *(p+1) == '/') {
return false;
return false;
}
} else {
return false; // do not permit '/' unless it's class name
}
}
if (type == ClassFileParser::LegalMethod && (ch == '<' || ch == '>')) {
return false; // do not permit '<' or '>' in method names
}
p++;
} else {
char* tmp_p = UTF8::next(p, &ch);
p = tmp_p;
break;
case '<':
case '>':
// do not permit '<' or '>' in method names
if (type == ClassFileParser::LegalMethod) {
return false;
}
}
}
return true;
}
// Take pointer to a string. Skip over the longest part of the string that could
// Take pointer to a UTF8 byte string (not NUL-terminated).
// Skip over the longest part of the string that could
// be taken as a fieldname. Allow '/' if slash_ok is true.
// Return a pointer to just past the fieldname.
// Return NULL if no fieldname at all was found, or in the case of slash_ok
// being true, we saw consecutive slashes (meaning we were looking for a
// qualified path but found something that was badly-formed).
static const char* skip_over_field_name(const char* name,
static const char* skip_over_field_name(const char* const name,
bool slash_ok,
unsigned int length) {
const char* p;
@ -5067,29 +5024,12 @@ static const char* skip_over_field_name(const char* name,
// Check if ch is Java identifier start or is Java identifier part
// 4672820: call java.lang.Character methods directly without generating separate tables.
EXCEPTION_MARK;
// return value
JavaValue result(T_BOOLEAN);
// Set up the arguments to isJavaIdentifierStart and isJavaIdentifierPart
// Set up the arguments to isJavaIdentifierStart or isJavaIdentifierPart
JavaCallArguments args;
args.push_int(unicode_ch);
// public static boolean isJavaIdentifierStart(char ch);
JavaCalls::call_static(&result,
SystemDictionary::Character_klass(),
vmSymbols::isJavaIdentifierStart_name(),
vmSymbols::int_bool_signature(),
&args,
THREAD);
if (HAS_PENDING_EXCEPTION) {
CLEAR_PENDING_EXCEPTION;
return 0;
}
if (result.get_jboolean()) {
continue;
}
if (not_first_ch) {
// public static boolean isJavaIdentifierPart(char ch);
JavaCalls::call_static(&result,
@ -5098,15 +5038,21 @@ static const char* skip_over_field_name(const char* name,
vmSymbols::int_bool_signature(),
&args,
THREAD);
if (HAS_PENDING_EXCEPTION) {
CLEAR_PENDING_EXCEPTION;
return 0;
}
if (result.get_jboolean()) {
continue;
}
} else {
// public static boolean isJavaIdentifierStart(char ch);
JavaCalls::call_static(&result,
SystemDictionary::Character_klass(),
vmSymbols::isJavaIdentifierStart_name(),
vmSymbols::int_bool_signature(),
&args,
THREAD);
}
if (HAS_PENDING_EXCEPTION) {
CLEAR_PENDING_EXCEPTION;
return NULL;
}
if(result.get_jboolean()) {
continue;
}
}
return (not_first_ch) ? old_p : NULL;
@ -5114,7 +5060,8 @@ static const char* skip_over_field_name(const char* name,
return (not_first_ch) ? p : NULL;
}
// Take pointer to a string. Skip over the longest part of the string that could
// Take pointer to a UTF8 byte string (not NUL-terminated).
// Skip over the longest part of the string that could
// be taken as a field signature. Allow "void" if void_ok.
// Return a pointer to just past the signature.
// Return NULL if no legal signature is found.
@ -5147,18 +5094,12 @@ const char* ClassFileParser::skip_over_field_signature(const char* signature,
}
else {
// Skip leading 'L' and ignore first appearance of ';'
length--;
signature++;
char* c = strchr((char*) signature, ';');
const char* c = (const char*) memchr(signature, ';', length - 1);
// Format check signature
if (c != NULL) {
ResourceMark rm(THREAD);
int newlen = c - (char*) signature;
char* sig = NEW_RESOURCE_ARRAY(char, newlen + 1);
strncpy(sig, signature, newlen);
sig[newlen] = '\0';
bool legal = verify_unqualified_name(sig, newlen, LegalClass);
bool legal = verify_unqualified_name(signature, newlen, LegalClass);
if (!legal) {
classfile_parse_error("Class name contains illegal character "
"in descriptor in class file %s",
@ -5192,8 +5133,8 @@ const char* ClassFileParser::skip_over_field_signature(const char* signature,
void ClassFileParser::verify_legal_class_name(const Symbol* name, TRAPS) const {
if (!_need_verify || _relax_verify) { return; }
char buf[fixed_buffer_size];
char* bytes = name->as_utf8_flexible_buffer(THREAD, buf, fixed_buffer_size);
assert(name->refcount() > 0, "symbol must be kept alive");
char* bytes = (char*)name->bytes();
unsigned int length = name->utf8_length();
bool legal = false;
@ -5221,7 +5162,7 @@ void ClassFileParser::verify_legal_class_name(const Symbol* name, TRAPS) const {
Exceptions::fthrow(
THREAD_AND_LOCATION,
vmSymbols::java_lang_ClassFormatError(),
"Illegal class name \"%s\" in class file %s", bytes,
"Illegal class name \"%.*s\" in class file %s", length, bytes,
_class_name->as_C_string()
);
return;
@ -5232,8 +5173,7 @@ void ClassFileParser::verify_legal_class_name(const Symbol* name, TRAPS) const {
void ClassFileParser::verify_legal_field_name(const Symbol* name, TRAPS) const {
if (!_need_verify || _relax_verify) { return; }
char buf[fixed_buffer_size];
char* bytes = name->as_utf8_flexible_buffer(THREAD, buf, fixed_buffer_size);
char* bytes = (char*)name->bytes();
unsigned int length = name->utf8_length();
bool legal = false;
@ -5255,7 +5195,7 @@ void ClassFileParser::verify_legal_field_name(const Symbol* name, TRAPS) const {
Exceptions::fthrow(
THREAD_AND_LOCATION,
vmSymbols::java_lang_ClassFormatError(),
"Illegal field name \"%s\" in class %s", bytes,
"Illegal field name \"%.*s\" in class %s", length, bytes,
_class_name->as_C_string()
);
return;
@ -5267,8 +5207,7 @@ void ClassFileParser::verify_legal_method_name(const Symbol* name, TRAPS) const
if (!_need_verify || _relax_verify) { return; }
assert(name != NULL, "method name is null");
char buf[fixed_buffer_size];
char* bytes = name->as_utf8_flexible_buffer(THREAD, buf, fixed_buffer_size);
char* bytes = (char*)name->bytes();
unsigned int length = name->utf8_length();
bool legal = false;
@ -5293,7 +5232,7 @@ void ClassFileParser::verify_legal_method_name(const Symbol* name, TRAPS) const
Exceptions::fthrow(
THREAD_AND_LOCATION,
vmSymbols::java_lang_ClassFormatError(),
"Illegal method name \"%s\" in class %s", bytes,
"Illegal method name \"%.*s\" in class %s", length, bytes,
_class_name->as_C_string()
);
return;
@ -5307,8 +5246,7 @@ void ClassFileParser::verify_legal_field_signature(const Symbol* name,
TRAPS) const {
if (!_need_verify) { return; }
char buf[fixed_buffer_size];
const char* const bytes = signature->as_utf8_flexible_buffer(THREAD, buf, fixed_buffer_size);
const char* const bytes = (const char* const)signature->bytes();
const unsigned int length = signature->utf8_length();
const char* const p = skip_over_field_signature(bytes, false, length, CHECK);
@ -5337,8 +5275,7 @@ int ClassFileParser::verify_legal_method_signature(const Symbol* name,
}
unsigned int args_size = 0;
char buf[fixed_buffer_size];
const char* p = signature->as_utf8_flexible_buffer(THREAD, buf, fixed_buffer_size);
const char* p = (const char*)signature->bytes();
unsigned int length = signature->utf8_length();
const char* nextp;
@ -5744,6 +5681,18 @@ void ClassFileParser::fill_instance_klass(InstanceKlass* ik, bool changed_by_loa
debug_only(ik->verify();)
}
void ClassFileParser::update_class_name(Symbol* new_class_name) {
// Decrement the refcount in the old name, since we're clobbering it.
_class_name->decrement_refcount();
_class_name = new_class_name;
// Increment the refcount of the new name.
// Now the ClassFileParser owns this name and will decrement in
// the destructor.
_class_name->increment_refcount();
}
// For an unsafe anonymous class that is in the unnamed package, move it to its host class's
// package by prepending its host class's package name to its class name and setting
// its _class_name field.
@ -5755,21 +5704,22 @@ void ClassFileParser::prepend_host_package_name(const InstanceKlass* unsafe_anon
ClassLoader::package_from_name(unsafe_anonymous_host->name()->as_C_string(), NULL);
if (host_pkg_name != NULL) {
size_t host_pkg_len = strlen(host_pkg_name);
int host_pkg_len = (int)strlen(host_pkg_name);
int class_name_len = _class_name->utf8_length();
char* new_anon_name =
NEW_RESOURCE_ARRAY(char, host_pkg_len + 1 + class_name_len);
// Copy host package name and trailing /.
strncpy(new_anon_name, host_pkg_name, host_pkg_len);
new_anon_name[host_pkg_len] = '/';
// Append unsafe anonymous class name. The unsafe anonymous class name can contain odd
// characters. So, do a strncpy instead of using sprintf("%s...").
strncpy(new_anon_name + host_pkg_len + 1, (char *)_class_name->base(), class_name_len);
int symbol_len = host_pkg_len + 1 + class_name_len;
char* new_anon_name = NEW_RESOURCE_ARRAY(char, symbol_len + 1);
int n = os::snprintf(new_anon_name, symbol_len + 1, "%s/%.*s",
host_pkg_name, class_name_len, _class_name->base());
assert(n == symbol_len, "Unexpected number of characters in string");
// Decrement old _class_name to avoid leaking.
_class_name->decrement_refcount();
// Create a symbol and update the anonymous class name.
_class_name = SymbolTable::new_symbol(new_anon_name,
(int)host_pkg_len + 1 + class_name_len,
CHECK);
// The new class name is created with a refcount of one. When installed into the InstanceKlass,
// it'll be two and when the ClassFileParser destructor runs, it'll go back to one and get deleted
// when the class is unloaded.
_class_name = SymbolTable::new_symbol(new_anon_name, symbol_len, CHECK);
}
}
@ -5815,6 +5765,7 @@ ClassFileParser::ClassFileParser(ClassFileStream* stream,
TRAPS) :
_stream(stream),
_requested_name(name),
_class_name(NULL),
_loader_data(loader_data),
_unsafe_anonymous_host(unsafe_anonymous_host),
_cp_patches(cp_patches),
@ -5873,6 +5824,7 @@ ClassFileParser::ClassFileParser(ClassFileStream* stream,
_max_bootstrap_specifier_index(-1) {
_class_name = name != NULL ? name : vmSymbols::unknown_class_name();
_class_name->increment_refcount();
assert(THREAD->is_Java_thread(), "invariant");
assert(_loader_data != NULL, "invariant");
@ -5942,6 +5894,8 @@ void ClassFileParser::clear_class_metadata() {
// Destructor to clean up
ClassFileParser::~ClassFileParser() {
_class_name->decrement_refcount();
if (_cp != NULL) {
MetadataFactory::free_metadata(_loader_data, _cp);
}
@ -6095,9 +6049,8 @@ void ClassFileParser::parse_stream(const ClassFileStream* const stream,
Symbol* const class_name_in_cp = cp->klass_name_at(_this_class_index);
assert(class_name_in_cp != NULL, "class_name can't be null");
// Update _class_name which could be null previously
// to reflect the name in the constant pool
_class_name = class_name_in_cp;
// Update _class_name to reflect the name in the constant pool
update_class_name(class_name_in_cp);
// Don't need to check whether this class name is legal or not.
// It has been checked when constant pool is parsed.
@ -6160,7 +6113,7 @@ void ClassFileParser::parse_stream(const ClassFileStream* const stream,
// For the boot and platform class loaders, skip classes that are not found in the
// java runtime image, such as those found in the --patch-module entries.
// These classes can't be loaded from the archive during runtime.
if (!ClassLoader::is_modules_image(stream->source()) && strncmp(stream->source(), "jrt:", 4) != 0) {
if (!stream->from_boot_loader_modules_image() && strncmp(stream->source(), "jrt:", 4) != 0) {
skip = true;
}