--- a/hotspot/make/windows/makefiles/sa.make Mon Nov 10 19:52:28 2014 -0500
+++ b/hotspot/make/windows/makefiles/sa.make Tue Nov 11 16:54:24 2014 +0000
@@ -122,7 +122,7 @@
SA_LFLAGS = $(SA_LFLAGS) -map -debug
!endif
!if "$(BUILDARCH)" == "i486"
-SA_LFLAGS = $(SAFESEH_FLAG) $(SA_LFLAGS)
+SA_LFLAGS = /SAFESEH $(SA_LFLAGS)
!endif
SA_CFLAGS = $(SA_CFLAGS) $(MP_FLAG)
--- a/hotspot/src/share/vm/classfile/classFileParser.cpp Mon Nov 10 19:52:28 2014 -0500
+++ b/hotspot/src/share/vm/classfile/classFileParser.cpp Tue Nov 11 16:54:24 2014 +0000
@@ -2059,7 +2059,7 @@
u2** localvariable_table_start;
u2* localvariable_type_table_length;
u2** localvariable_type_table_start;
- u2 method_parameters_length = 0;
+ int method_parameters_length = -1;
u1* method_parameters_data = NULL;
bool method_parameters_seen = false;
bool parsed_code_attribute = false;
@@ -2278,7 +2278,8 @@
}
method_parameters_seen = true;
method_parameters_length = cfs->get_u1_fast();
- if (method_attribute_length != (method_parameters_length * 4u) + 1u) {
+ const u2 real_length = (method_parameters_length * 4u) + 1u;
+ if (method_attribute_length != real_length) {
classfile_parse_error(
"Invalid MethodParameters method attribute length %u in class file",
method_attribute_length, CHECK_(nullHandle));
@@ -2288,7 +2289,7 @@
cfs->skip_u2_fast(method_parameters_length);
// ignore this attribute if it cannot be reflected
if (!SystemDictionary::Parameter_klass_loaded())
- method_parameters_length = 0;
+ method_parameters_length = -1;
} else if (method_attribute_name == vmSymbols::tag_synthetic()) {
if (method_attribute_length != 0) {
classfile_parse_error(
--- a/hotspot/src/share/vm/oops/constMethod.cpp Mon Nov 10 19:52:28 2014 -0500
+++ b/hotspot/src/share/vm/oops/constMethod.cpp Tue Nov 11 16:54:24 2014 +0000
@@ -116,7 +116,11 @@
if (sizes->generic_signature_index() != 0) {
extra_bytes += sizeof(u2);
}
- if (sizes->method_parameters_length() > 0) {
+ // This has to be a less-than-or-equal check, because we might be
+ // storing information from a zero-length MethodParameters
+ // attribute. We have to store these, because in some cases, they
+ // cause the reflection API to throw a MalformedParametersException.
+ if (sizes->method_parameters_length() >= 0) {
extra_bytes += sizeof(u2);
extra_bytes += sizes->method_parameters_length() * sizeof(MethodParametersElement);
}
@@ -237,7 +241,7 @@
_flags |= _has_linenumber_table;
if (sizes->generic_signature_index() != 0)
_flags |= _has_generic_signature;
- if (sizes->method_parameters_length() > 0)
+ if (sizes->method_parameters_length() >= 0)
_flags |= _has_method_parameters;
if (sizes->checked_exceptions_length() > 0)
_flags |= _has_checked_exceptions;
@@ -272,7 +276,7 @@
if (sizes->generic_signature_index() != 0)
*(generic_signature_index_addr()) = sizes->generic_signature_index();
// New data should probably go here.
- if (sizes->method_parameters_length() > 0)
+ if (sizes->method_parameters_length() >= 0)
*(method_parameters_length_addr()) = sizes->method_parameters_length();
if (sizes->checked_exceptions_length() > 0)
*(checked_exceptions_length_addr()) = sizes->checked_exceptions_length();
@@ -283,7 +287,7 @@
}
int ConstMethod::method_parameters_length() const {
- return has_method_parameters() ? *(method_parameters_length_addr()) : 0;
+ return has_method_parameters() ? *(method_parameters_length_addr()) : -1;
}
MethodParametersElement* ConstMethod::method_parameters_start() const {
--- a/hotspot/src/share/vm/oops/constMethod.hpp Mon Nov 10 19:52:28 2014 -0500
+++ b/hotspot/src/share/vm/oops/constMethod.hpp Tue Nov 11 16:54:24 2014 +0000
@@ -372,6 +372,11 @@
ExceptionTableElement* exception_table_start() const;
// method parameters table
+
+ // This returns -1 if no parameters are present, a non-negative
+ // value otherwise. Note: sometimes, there are 0-length parameters
+ // attributes that must be reported up to the reflection API all the
+ // same.
int method_parameters_length() const;
MethodParametersElement* method_parameters_start() const;
--- a/hotspot/src/share/vm/prims/jvm.cpp Mon Nov 10 19:52:28 2014 -0500
+++ b/hotspot/src/share/vm/prims/jvm.cpp Tue Nov 11 16:54:24 2014 +0000
@@ -1657,7 +1657,17 @@
Handle reflected_method (THREAD, JNIHandles::resolve_non_null(method));
const int num_params = mh->method_parameters_length();
- if (0 != num_params) {
+ if (num_params < 0) {
+ // A -1 return value from method_parameters_length means there is no
+ // parameter data. Return null to indicate this to the reflection
+ // API.
+ assert(num_params == -1, "num_params should be -1 if it is less than zero");
+ return (jobjectArray)NULL;
+ } else {
+ // Otherwise, we return something up to reflection, even if it is
+ // a zero-length array. Why? Because in some cases this can
+ // trigger a MalformedParametersException.
+
// make sure all the symbols are properly formatted
for (int i = 0; i < num_params; i++) {
MethodParametersElement* params = mh->method_parameters_start();
@@ -1685,8 +1695,6 @@
result->obj_at_put(i, param);
}
return (jobjectArray)JNIHandles::make_local(env, result());
- } else {
- return (jobjectArray)NULL;
}
}
JVM_END
--- a/hotspot/src/share/vm/runtime/reflection.cpp Mon Nov 10 19:52:28 2014 -0500
+++ b/hotspot/src/share/vm/runtime/reflection.cpp Tue Nov 11 16:54:24 2014 +0000
@@ -806,17 +806,16 @@
oop Reflection::new_parameter(Handle method, int index, Symbol* sym,
int flags, TRAPS) {
- Handle name;
- // A null symbol here translates to the empty string
+ Handle rh = java_lang_reflect_Parameter::create(CHECK_NULL);
+
if(NULL != sym) {
- name = java_lang_String::create_from_symbol(sym, CHECK_NULL);
+ Handle name = java_lang_String::create_from_symbol(sym, CHECK_NULL);
+ java_lang_reflect_Parameter::set_name(rh(), name());
} else {
- name = java_lang_String::create_from_str("", CHECK_NULL);
+ java_lang_reflect_Parameter::set_name(rh(), NULL);
}
- Handle rh = java_lang_reflect_Parameter::create(CHECK_NULL);
- java_lang_reflect_Parameter::set_name(rh(), name());
java_lang_reflect_Parameter::set_modifiers(rh(), flags);
java_lang_reflect_Parameter::set_executable(rh(), method());
java_lang_reflect_Parameter::set_index(rh(), index);