--- a/src/hotspot/share/classfile/classFileParser.cpp Tue Jan 22 14:14:52 2019 -0800
+++ b/src/hotspot/share/classfile/classFileParser.cpp Tue Mar 26 10:55:17 2019 -0700
@@ -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 @@
}
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 @@
}
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 @@
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 @@
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 @@
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 @@
// 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 @@
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 @@
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 @@
}
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 @@
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 @@
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_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 @@
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 @@
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 @@
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 @@
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 @@
}
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 @@
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 @@
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 @@
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 @@
_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 @@
// Destructor to clean up
ClassFileParser::~ClassFileParser() {
+ _class_name->decrement_refcount();
+
if (_cp != NULL) {
MetadataFactory::free_metadata(_loader_data, _cp);
}
@@ -6095,9 +6049,8 @@
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 @@
// 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;
}