Name: mf23781 Date: 06/23/98
A trap occured when debugging a defect, running
execution04501 on an SMP machine.
Initial analysis showed the following cause.
Thread 8 trapped executing opc_invokenonvirtual_quick
The reason was the the constant pool reference was wrong:
case opc_invokenonvirtual_quick:
mb = constant_pool[GET_INDEX(pc + 1)].mb; <=== trap here
args_size = mb->args_size;
optop -= args_size;
frame->returnpc = pc + 3;
o = S_HANDLE(0);
if (o == 0)
JAVA_ERROR("NullPointerException", 0);
goto callmethod;
PC = 0D677EC1
dump
0D677EC0 2A DC 01 01 B1
aload_0
invokeignored_quick
return
but the code is actually in a switch statement for invokenonvirtual_quick
This code seems to be for the <init> method of execution04501b
However thread 4 is also executing this code at this address,
and has just finished rewriting the byte codes.
The problem seems to be that one thread starts to execute a
invokespecial opcode, and resolves the method reference from the constant
pool and rewrites it as a invokenonvirtual_quick.
A second thread starts to execute the invokenonvirtual_quick opcode and gets
as far as doing the switch statement on the opcode.
The first thread then continues to run, and rewrites the target method
as inline code, and then updates and replaces the invoke call. In this case
the code doesn't do anything (as it is the defaualt constructor from Object),
so it is rewritten as invokeignore_quick. The parameters are changes to
01 01, indicating 1 argument, and the object reference should be checked
as being non-null.
The second thread the continues to execute, and reads the 01 01 as an index
into the constant pool for the invokenonvirtual_quick object.
This then traps.
Disabling inlining by returning NO_INLINING_FLAG from
static unsigned long
MethodInlining(struct methodblock *mb) {
may reduce the problem.
The problem occurred about 1 in 3-4 times without the fix.
With the fix, it ran 5 times OK, then hung on the 6th.
This was because thread 6 was blocked on CODE_LOCK.
The only other threads were 1,2,3.
Javasoft seem to have allowed for code rewriting by testing the opcode
compared to the first reading, (after having read the rest of the
operands of the instruction) then retrying the loop again with
a SIZE_AND_STACK(0, 0)
Even if the JVM tested the opcode again just before reading the operand
then this may not be safe, as if code is updated with a memcpy() inside a
CODE_LOCK() CODE_UNLOCK() pair, then the update using memcpy is
still not atomic if the opcodes are read outside a CODE_LOCK() block.
Code that can be rewritten perhaps includes any of the following
opcodes:
opc_invokenonvirtual_quick
opc_invokesuper_quick
opc_invokevirtual_quick_w
opc_invokestatic_quick
opc_invokeinterface_quick
opc_invokevirtualobject_quick
See Sun bug 4066650, reported against 1.2
This was reported as fixed in 1.2Beta2
Sun said that this was reproduced in 1.1, but there
is no reference to a fix at this level.
I am not sure if this solves the problem, or just tries to do the rewriting
early, when we still have a code lock and the opcode has not been rewritten
to a quick instruction. Rewriting could be safe at that point, but not
after the quick rewrite, as someone else could execute the instruction
without locking.
Also, bug 4077463 may be relevant
This needs to be fixed in the 1.1.x level
======================================================================
- duplicates
-
JDK-4265842 jdk 1.1.6ri causes heep corruption and random core dumps
-
- Closed
-
-
JDK-4337029 NT multiprocessor crash with threads & sockets: c0000005 (access violation)
-
- Closed
-