Issue | Fix Version | Assignee | Priority | Status | Resolution | Resolved In Build |
---|---|---|---|---|---|---|
JDK-2125186 | 5.0u4 | Daniel Daugherty | P4 | Resolved | Fixed | b03 |
Misha reported the following RedefineClasses problem:
Date: Mon, 07 Mar 2005 22:44:39 -0800
From: ###@###.###
Subject: A problem with redefined java.lang.reflect.Method.invoke()
Hi guys,
I've recently discovered one more problem with method redefinition.
Actually, it should have been there forever, it's just that the code that
is problematic seems to be exercised quite rarely. It seems to me now
that I've seen problems like this in the past, but they were in big apps
like some App servers, that could just ignore such issues and proceed,
or some such.
The problem is that the VM initializes an internal variable, a methodOop
for java.lang.reflect.Method.invoke() method early, and then uses it
in some access rights checks. So if Method.invoke() is redefined, some
(but not all) reflection calls may fail. Look at the code below that is
from 1.4.2 JVM, vframe.cpp source file:
// Step back n frames, skip and pseudo frames in between.
// This function is used in Class.forName, Class.newInstance, Method.Invoke,
// AccessController.doPrivileged.
//
// NOTE that in JDK 1.4 this has been exposed to Java as
// sun.reflect.Reflection.getCallerClass(), which can be inlined.
// Inlined versions must match this routine's logic. See, for example,
// Parse::inline_native_Reflection_getCallerClass in
// opto/library_call.cpp.
void vframeStreamCommon::security_get_caller_frame(int depth) {
while (depth-- > 0) {
// skip Method.invoke() and auxiliary frames
skip_method_invoke_and_aux_frames();
if (at_end()) return;
// Skip real frame
next();
}
// skip Method.invoke() and auxiliary frames
skip_method_invoke_and_aux_frames();
}
void vframeStreamCommon::skip_method_invoke_and_aux_frames() {
while (!at_end() &&
(/*method() == Universe::reflect_invoke_method() */
//We replace the above code with the check that works for redefined java.lang.reflect.Method.invoke()
(method()->method_holder() == SystemDictionary::reflect_method_klass() &&
method()->name() == vmSymbols::invoke_name() &&
method()->signature() == vmSymbols::object_array_object_object_signature())
|| (Universe::is_gte_jdk14x_version() && UseNewReflection &&
Klass::cast(method()->method_holder())->is_subclass_of(SystemDictionary::reflect_method_accessor_klass())))) {
next();
}
}
The 'skip_method_invoke_and_aux_frames()' above already contains the
original single code line commented out, and my fix for this problem
(not sure it's the best possible one, but anyway, it works) in the next 3
lines. I have a JFluid test which demonstrates how the original VM code
fails when Method.invoke() is redefined, and how this code works. It
looks like in Mustang the problem is there as well, though I didn't look
at its source code.
No doubt a simpler test for this bug can be created. It just looks like
the method that is invoked shouldn't be public and/or there should be
some other non-obvious condition, which you can find out by looking at
the relevant JDK code. Let me know if you would like me to do that.
Let me know what you think about this issue.
Misha
###@###.### 2005-03-08 19:18:11 GMT
Date: Mon, 07 Mar 2005 22:44:39 -0800
From: ###@###.###
Subject: A problem with redefined java.lang.reflect.Method.invoke()
Hi guys,
I've recently discovered one more problem with method redefinition.
Actually, it should have been there forever, it's just that the code that
is problematic seems to be exercised quite rarely. It seems to me now
that I've seen problems like this in the past, but they were in big apps
like some App servers, that could just ignore such issues and proceed,
or some such.
The problem is that the VM initializes an internal variable, a methodOop
for java.lang.reflect.Method.invoke() method early, and then uses it
in some access rights checks. So if Method.invoke() is redefined, some
(but not all) reflection calls may fail. Look at the code below that is
from 1.4.2 JVM, vframe.cpp source file:
// Step back n frames, skip and pseudo frames in between.
// This function is used in Class.forName, Class.newInstance, Method.Invoke,
// AccessController.doPrivileged.
//
// NOTE that in JDK 1.4 this has been exposed to Java as
// sun.reflect.Reflection.getCallerClass(), which can be inlined.
// Inlined versions must match this routine's logic. See, for example,
// Parse::inline_native_Reflection_getCallerClass in
// opto/library_call.cpp.
void vframeStreamCommon::security_get_caller_frame(int depth) {
while (depth-- > 0) {
// skip Method.invoke() and auxiliary frames
skip_method_invoke_and_aux_frames();
if (at_end()) return;
// Skip real frame
next();
}
// skip Method.invoke() and auxiliary frames
skip_method_invoke_and_aux_frames();
}
void vframeStreamCommon::skip_method_invoke_and_aux_frames() {
while (!at_end() &&
(/*method() == Universe::reflect_invoke_method() */
//We replace the above code with the check that works for redefined java.lang.reflect.Method.invoke()
(method()->method_holder() == SystemDictionary::reflect_method_klass() &&
method()->name() == vmSymbols::invoke_name() &&
method()->signature() == vmSymbols::object_array_object_object_signature())
|| (Universe::is_gte_jdk14x_version() && UseNewReflection &&
Klass::cast(method()->method_holder())->is_subclass_of(SystemDictionary::reflect_method_accessor_klass())))) {
next();
}
}
The 'skip_method_invoke_and_aux_frames()' above already contains the
original single code line commented out, and my fix for this problem
(not sure it's the best possible one, but anyway, it works) in the next 3
lines. I have a JFluid test which demonstrates how the original VM code
fails when Method.invoke() is redefined, and how this code works. It
looks like in Mustang the problem is there as well, though I didn't look
at its source code.
No doubt a simpler test for this bug can be created. It just looks like
the method that is invoked shouldn't be public and/or there should be
some other non-obvious condition, which you can find out by looking at
the relevant JDK code. Let me know if you would like me to do that.
Let me know what you think about this issue.
Misha
###@###.### 2005-03-08 19:18:11 GMT
- backported by
-
JDK-2125186 cached methodOops in universe class confuse RedefineClasses
-
- Resolved
-