Hi all,
i have following classes:
Start.class:
package com;
import java.awt.Color;
public class Start
{
public static void main(String[] args)
{
new BuhDiag().setBackground(Color.BLACK);
}
}
and
BuhDiag.class:
package com;
import java.awt.Color;
import javax.swing.JDialog;
public class BuhDiag extends JDialog
{
private static final long serialVersionUID = 1L;
public void setBackground(Color c)
{
super.setBackground(c);
}
}
I coded this example to research a problem i had with a custom application. Even if that sample is senseless it is the same scenario i had with that custom application.
As you can see the Start class is a simple class, which creates an BuhDiag-Object and invokes the method setBackground(). Nothing interesting here. Lets take a look at BuhDiag and it attributes. BuhDiag extends JDialog and as setBackground is a method of JDialog I overwrote with my own method by calling super.setBackground(). Also nothing unusual here. So know lets take a look at bytecode level.
General Information on Start.class:
AccessFlags: 0x00000021
SuperClass: java/lang/Object
Bytecode of Start.main():
0 new #16 <com/BuhDiag>
3 dup
4 invokespecial #18 <com/BuhDiag.<init>>
7 getstatic #19 <java/awt/Color.BLACK>
10 invokevirtual #25 <com/BuhDiag.setBackground>
13 return
General information of BuhDiag.class:
AccessFlags: 0x00000021
SuperClass: javax/swing/JDialog
Bytecode BuhDiag.setBackground():
Signature: (Jjava/awt/Color;)V
0 aload_0
1 aload_1
2 invokespecial #21 <javax/swing/JDialog.setBackground>
5 return
Pretty straight forward compiler generated code. What I know do is following:
1. Cut off the bytecode of BuhDiag.setBackground and i insert a trampoulin which calles another method which contains the the original code of setBackground with a few modifications:
Take a look at the method here:
0 aload 2
2 astore 0
4 aload_0
5 aload_1
6 invokespecial #21 <javax/swing/JDialog.setBackground>
9 return
as you can see i overwrite this instance at slot zero with the instance stored in slot 2 ( indeed slot 2 holds the original this-instance ). After this instance is overwritte the code is left untouched as you can see. The overwritten this-instance is pushed on the stack after that the color is pushed and the super method is invoked.
From my point of view this should work. I also took into account that the class which contains the cut off bytecodes from the originial setBackground method must have the same super class at BuhDiag.class
Now i got following exception:
D:\samples\prot>java -jar extendTest2.jar
-----------------------------------------------------------> Protected Method called! ID = "1", NAME = ""
Exception in thread "main" java.lang.VerifyError: (class: TPMHQC6z3QxHAjyI, method: VTaCiQuHjHQ35SGz signature: (Ljava/a
wt/Color;Lcom/BuhDiag;)V) Incompatible object argument for invokespecial
at java.lang.Class.getDeclaredConstructors0(Native Method)
at java.lang.Class.privateGetDeclaredConstructors(Unknown Source)
at java.lang.Class.getConstructor0(Unknown Source)
at java.lang.Class.newInstance0(Unknown Source)
at java.lang.Class.newInstance(Unknown Source)
at com.xxx.XXX(zzzzzzz.java:58)
at com.xxx.XXX(yyyyyyy.java:254)
at com.xxx.XXX(wwwwww.java:147)
at com.xxx.XXX(bbbbbb.java:68)
at com.BuhDiag.setBackground(BuhDiag.java)
at com.Start.main(Start.java:9)
It seems to me that calling the invokespecial with the overwritten this-instance is causing the error.
I hope i can find a way to solve this problem. If this is not working my whole concept will go to hell ;(
Maybe somebody can point me the right way.
Thank you in advance,
bgnahm
PS: What i also did was exchanging that invokespecial with invokevirtual but this ends in an infinite loop. I thought may because the passed this-Instance is not from the class which executes the cut-off bytecodes i should maybe use the usual instance invokation mechanism... no luck here ;(
Edited by: bgnahm on Jul 15, 2010 8:34 AM