|
Quick Lists
|
|
Bug ID:
|
4514956
|
|
Votes
|
0
|
|
Synopsis
|
Method.isObsolete() returns false for redefined method
|
|
Category
|
hotspot:test
|
|
Reported Against
|
merlin-beta3
|
|
Release Fixed
|
1.4.1(hopper)
|
|
State
|
11-Closed,
Verified,
bug
|
|
Priority:
|
4-Low
|
|
Related Bugs
|
4287595
,
4531511
|
|
Submit Date
|
15-OCT-2001
|
|
Description
|
This is the specification for Method.isObsolete():
public boolean isObsolete()
Determine if this method is obsolete.
Returns:
true if this method has been replaced by
a non-equivalent method using
VirtualMachine.redefineClasses(java.util.Map).
Although the specification doesn't define the meaning of
the term "equivalent" in the context of the specification,
the meaning is in the specification for
the JVMDI function Redefine Classes
(http://java.sun.com/j2se/1.4/docs/guide/jpda/
jvmdi-spec.html#RedefineClasses):
An original and a redefined method should be considered
equivalent if:
their bytecodes are the same except for indicies into
the constant pool and
the referenced constants are equal.
However, the test against the Method.isObsolete()
developed on the basis of the above specifications shows
that isObsolete() being invoked on the Method customer
mirroring a method whose body has been fully replaced when
the method VirtualMachine.redefineClass had been invoked on
the ReferenceType customer mirroring the class containing the method,
returns false.
This result is observed
when HS 1.4.0-beta3-b83 is runnning a test program
on the following H/S configurations:
- SUNW Ultra1: sparc 200MHz, RAM 128Mb;
OS: Solaris-8;
JVM: Client & Server
- customer : 2-processor i686 600MHz processor, RAM 512Mb;
OS: Solaris-8;
JVM: Client & Server
- customer : 2-processor i686 600MHz processor, RAM 512Mb;
OS: Linux/RedHat6.2;
JVM: Client & Server
- customer : Pentium-II 350MHz, RAM 128Mb;
OS: WinNT/4-Workstation;
JVM: Client & Server
Corresponding code fragments in a debugger and a debuggee
and corresponding log for the tested case are below.
Steps to reproduce the bug:
1. cd /net/sqesvr.sfbay/export/vsn/GammaBase/Bugs/{this bug ID}
2. sh doit.sh {JAVA_HOME}
This bug affects the following testbase_nsk tests:
nsk/jdi/Method/isObsolete/isobsolete002
The tests will be in the next release of testbase_nsk;
the current release of testbase_nsk (1.4) is accessible through:
/net/sqesvr.sfbay/export/vsn/VM/testbase/testbase_nsk.v14
///////////////////////////////////////////////////////////////////////
// code fragments in the debugger
String className = "nsk.jdi.Method.isObsolete.isobsolete002b";
String methodName = "m2";
ReferenceType redefClass = null;
switch (i) {
case 0:
log2("......getting: List classes =
vm.classesByName(className);");
List classes = vm.classesByName(className);
log2("......getting: redefClass = (ReferenceType)
classes.get(0);");
redefClass = (ReferenceType) classes.get(0);
log2("......getting: Method method = (Method)
redefClass.methodsByName(methodName).get(0);");
Method method = (Method)
redefClass.methodsByName(methodName).get(0);
log2("......getting: boolean isObs = method.isObsolete();");
boolean isObs = method.isObsolete();
if (isObs) {
log3("ERROR: method.isObsolete() == true");
testExitCode = FAILED;
} else
log2(" : method.isObsolete() == false");
try {
log2("......vm.redefineClasses(mapClassToBytes());");
vm.redefineClasses(mapClassToBytes());
} catch ( Exception e ) {
log3("ERROR: Exception: " + e);
testExitCode = FAILED;
throw e;
} catch ( Error e ) {
log3("ERROR: Error: " + e);
testExitCode = FAILED;
throw e;
}
log2("......getting: isObs = method.isObsolete();");
isObs = method.isObsolete();
if (isObs) {
log2(" : method.isObsolete() == true");
} else {
log3("ERROR: method.isObsolete() == false");
testExitCode = FAILED;
}
break;
default:
throw new JDITestRuntimeException ("** default case **");
}
=======================================================================
// code fragments in the debuggee
// --------------------file isobsolete002b.jav
public class isobsolete002b {
isobsolete002b() {
isobsolete002a.log1(" This is the class to be redefined");
}
static int i1 = 0;
static int i2 = 0;
static void m2() {
i1 = 1;
i2 = 1;
}
static void m1() {
isobsolete002a.log1("method m1: before m2()");
m2();
isobsolete002a.log1("method m1: after m2()");
}
}
// --------------------file isobsolete002b.ja
public class isobsolete002b {
isobsolete002b() {
isobsolete002a.log1(" This is the class to redefine");
}
static int i1 = 0;
static int i2 = 0;
static void m2() {
boolean b1 = true;
isobsolete002a.log1("redefining method: b1 " + b1);
}
static void m1() {
isobsolete002a.log1("method m1: before m2()");
m2();
isobsolete002a.log1("method m1: after m2()");
}
}
=======================================================================
// log with comments
==> nsk/jdi/Method/isObsolete/isobsolete002 TESTING BEGINS
--> debugger: breakpointForCommunication
debugee.stderr> **> debuggee: debuggee started!
debugee.stderr> **> debuggee: This is the class to be redefined
debugee.stderr> **> debuggee: method m1: before m2()
debugee.stderr> **> debuggee: method m1: after m2()
^^^^^^^^^^^^^^^^^^^^^^^^
no message between before and after
because m1() prints nothing
==> nsk/jdi/Method/isObsolete/isobsolete002 :::::: case: # 0
--> debugger: ......getting: List classes = vm.classesByName(className);
--> debugger: ......getting: redefClass = (ReferenceType) classes.get(0);
--> debugger: ......getting: Method method = (Method)
redefClass.methodsByName(methodName).get(0);
--> debugger: ......getting: boolean isObs = method.isObsolete();
--> debugger: : method.isObsolete() == false
--> debugger: ......vm.redefineClasses(mapClassToBytes());
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
--> debugger: ......getting: String[] args = argsHandler.getArguments();
--> debugger: ......File fileToBeRedefined = new File(fileToBeRedefinedName);
--> debugger: fileToBeRedefined.exists(); length == 776
^^^^^^^^^^^^^
--> debugger: ......File fileToRedefine = new File(fileToRedefineName);
--> debugger: fileToRedefine.exists(); length == 1026
^^^^^^^^^^^^^^
--> debugger: ......getting: isObs = method.isObsolete();
# ERROR: ##> debugger: ERROR: method.isObsolete() == false
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
debugee.stderr> **> debuggee: method m1: before m2()
debugee.stderr> **> debuggee: redefining method: b1 true
^^^^^^^^^^^^^^^^^^^^^^^^^^
message printed by new m2() method
debugee.stderr> **> debuggee: method m1: after m2()
--> debugger: breakpointForCommunication
==> nsk/jdi/Method/isObsolete/isobsolete002 TESTING ENDS
----------------------------------------------------------------------
======================================================================
Ivan Popov < xxxxx@xxxxx >
This bug affects also the following JDWP test from testbase_nsk:
nsk/jdwp/Method/IsObsolete/isobsolete002
======================================================================
|
|
Work Around
|
N/A
|
|
Evaluation
|
Need to look at for Hopper
xxxxx@xxxxx 2002-01-30
It is correct for isObsolete() to return false in this use case.
In the javadoc for VirtualMachine.redefineClasses() we have the
following:
All classes given are redefined according to the definitions
supplied. If any redefined methods have active stack frames,
those active frames continue to run the bytecodes of the
previous method. The redefined methods will be used on new
invokes.
The key phrase is:
"If any redefined methods have active stack frames,
those active frames continue to run the bytecodes of the
previous method."
Only in the case of those active stack frames will a call
to thread.frame(0).location().method().isObsolete()
return true. Thus you must be holding such a StackFrame
before or during the VirtualMachine.redefineClasses() call.
Any StackFrame or any Method lookup obtained after the
redefineClasses() will discover the redefined information,
and hence isObsolete() must correctly return false.
I conclude that this is a test bug and not a product bug.
See suggested fix.
Dostar Kasymov, xxxxx@xxxxx
I believe that the test case does not contradict to current specification
of isObsolete() method, which reads:
public boolean isObsolete()
Determine if this method is obsolete.
Returns:
true if this method has been replaced by
a non-equivalent method using
VirtualMachine.redefineClasses(java.util.Map).
This spec does say that true must be returned only in case when redefined
method has active stack frame.
One can understand (as well as the developer of this test case) the statement
"true if this method has been replaced by a non-equivalent method using ..."
as "true if redefinition with non-equivalent method occurred in the past
before isObsolete() invocation".
I filed rfe against JDI spec:
4633227 JDI spec: usage of methods implementing HotSwap feature needs clarification
Fix for the 4514956 is pending until decision on 4633227.
======================================================================
Fixed in testbase_nsk.v14r12, testbase_nsk.v131r12
The test was fixed in a following way.
Additional breakpoint is created for a location inside checked
method in order to suspend main debuggee's thread at the moment
of method execution. After breakpoint hit, redefineClasses
is invoked. New mirror of checked method is obtained via
mainThread.frame(0).location().method(). And then result of
isObsolete() is checked.
The test does not fail after this fix. Another test was also
fixed in the same way:
nsk/jdi/Method/isObsolete/isobsolete001
======================================================================
Ivan Popov < xxxxx@xxxxx >
One more JDWP test is fixed due to this bug:
nsk/jdwp/Method/IsObsolete/isobsolete002
After fixing the test successfully passes against Merlin-b92.
======================================================================
|
|
Comments
|
PLEASE NOTE: JDK6 is formerly known as Project Mustang
|
|
|
 |