*** Retry: If this post reaches you twice, I apologize *** This problem was brought to our attention by Toby Reyelts in October 2002, but was not really examined as much as I'd like :)
Many rewriting of existing methods rely on the *this* reference to be in slot 0. When a method is invoked a new stack frame is created by the virtual machine where the object reference to the object on which the method is invoked, i.e. in Java programming language is referred to as *this*, is placed in the first local variable slot indexed by 0. The object initialization method (<init>) is special, because slot 0 contains the uninitialized *this*, as explained in the VM Section 4.9.4 on how code is verified: "When doing dataflow analysis on instance methods, the verifier initializes local variable 0 to contain an object of the current class, or, for instance initialization methods, local variable 0 contains a special type indicating an uninitialized object. After an appropriate instance initialization method is invoked (from the current class or the current superclass) on this object, all occurrences of this special type on the verifier's model of the operand stack and in the local variable array are replaced by the current class type. The verifier rejects code that uses the new object before it has been initialized or that initializes the object more than once. In addition, it ensures that every normal return of the method has invoked an instance initialization method either in the class of this method or in the direct superclass." Reyelts said he'd seen bytecode which overwrites slot 0, so the "this" reference that's placed there when the method begins execution is lost, and thus cannot be relied on! He proposed a solutions where the *this* is stored in the first free local variable slot, which seems valid, BUT.. I created the following method that implements his proposal: public Initializer(); // javap lies, this is actually called "<init>" Signature: ()V 0: aload_0 ; load unitialized object from locvar slot 0 1: dup ; duplicate 2: astore N ; store the unitialized object in locvar slot 1 3: aconst_null 4: astore_0 ; store special null value in locvar slot 0 5: invokespecial #x; //Method java/lang/Object."<init>":()V 8: return which does nothing but load the slot, duplicate it, store it in the next free slot N and override the 0th slot with null. The object is eventually initialized, so local var slot N refers a initialized object that can be relied on to do whatever with. Now the problem, different verifiers yield different results, that is, the native verifier by sun accepts this class and sun's vm executes it perfectly, but JustIce returns this: ********************************************************************* Pass 3b, method number 0 ['public void <init>()']: VERIFIED_REJECTED Constraint violated in method 'public void <init>()': Instruction ASTORE constraint violated: Working on an uninitialized object '<UNINITIALIZED OBJECT OF TYPE 'Initializer'>'. InstructionHandle: 2: astore_1[76](1) Execution Frame: Local Variables: 0: <UNINITIALIZED OBJECT OF TYPE 'Initializer'> 1: <unknown object> 2: <unknown object> OperandStack: Slots used: 2 MaxStack: 2. <UNINITIALIZED OBJECT OF TYPE 'Initializer'> (Size: 1) <UNINITIALIZED OBJECT OF TYPE 'Initializer'> (Size: 1) Execution flow: 0: aload_0 [InstructionContext] 1: dup [InstructionContext] 2: astore_1 [InstructionContext] ********************************************************************* I think the source of the problem is the definition of _use_ as in "The verifier rejects code that uses the new object before it has been initialized or that initializes the object more than once." Anyone who can shed some light on this case?? What is correct? Is this a bug in JustIce or is Sun not obeying their own spec? --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
