Java Solaris Communities Sun Store Join SDN My Profile Why Join?
 
Bug Database
Bug Detail
Quick Lists
Top 25 Bugs
Top 25 RFE's
Recently Closed Bugs
Printable Page Printable Page


Bug Database
Bug ID: 6552803
Votes 1
Synopsis the moveToFront causes Heavyweight components to be removed.
Category java:classes_awt
Reported Against
Release Fixed 7(b21), 6u12(b02) (Bug ID:2169749)
State 10-Fix Delivered, Verified, bug
Priority: 4-Low
Related Bugs 6783411 , 4154448
Submit Date 02-MAY-2007
Description
FULL PRODUCT VERSION :
jre 1.6 b105

ADDITIONAL OS VERSION INFORMATION :
Windows XP SP2

A DESCRIPTION OF THE PROBLEM :
When selecting a JInternalFrame with a canvas using jni and the canvas is in a JPanel the moveToFront casues a componentZorder call which removes the Canvas and causes an invalid window handle that causes the jni code to break.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Actually someone on the Sun developer team developed a simple test example to show the exception trace. The example is on the java.net site message forum:

http://forums.java.net/jive/thread.jspa?threadID=25806&tstart=0


EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Should not cause movie that is in canvas to disappear.
ACTUAL -
Movie is unloaded from memory

ERROR MESSAGES/STACK TRACES THAT OCCUR :
Message in JNI code indicating WM_DESTROY and invalid window handle due to canvas peer being removed.

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
Actually someone on the Sun developer team develioped a simple test example to show the exception trace. The example is on the java.net site message forum:

http://forums.java.net/jive/thread.jspa?threadID=25806&tstart=0

---------- END SOURCE ----------
Posted Date : 2007-05-02 15:24:06.0
Work Around
N/A
Evaluation
We need to improve setComponentZOrder() not not remove peer in the described situation.
This will make lw&hw mixing even closer :)
Posted Date : 2007-05-03 07:18:01.0

The easiest way to get the expected results is to modify the isRemoveNotifyNeeded() method in order to allow skipping of removeNotify() for any LW component. The current logic is:

        if (comp.isLightweight()) {
            if (comp instanceof Container) {
                return ((Container)comp).hasHeavyweightDescendants();
            } else {
                return false;
            }
        }

The line that returns the result of the hasHWDesc() method could simply be modified to return false in any case. Nothing bad was observed when using this approach. Yet.

Though we might want to extend the logic in order to handle LW container containing HW children just the same way as regular HW components are handled.
Posted Date : 2007-07-27 12:42:22.0

The suggested fix successfully fixes the problem. Actually there's only one case left: the peer gets destroyed when the user minimizes the JInternalFrame. I'm in doubt whether this case should be fixed with this CR or be fixed at all.
Posted Date : 2007-08-01 13:39:58.0

The final idea of the fix is as follows. setComponentZOrder() actually verifies the return value of the isRemoveNotifyNeeded(Component comp, Container oldContainer, Container newContainer) to check whether it's necessary to remove the peer of the component. Thefore it is the isRemoveNotifyNeeded() method that should be fixed.

Our implementation of the method does some common checks:
1. If the oldContainer is null or the component has no peer curretnly, there's no need to remove the peer.
2. If the newContainer doesn't have a peer, we need to remove the peer from the component.

As the second step this method separates handling of LW and HW components.

1. If the component is LW:
a) If it's a Container, then return the result of the hasHeavyweightDescendants() method. That means that the peer gets destroyed if the LW container has any HW descendants.
b) Otherwise, simply return flase. The peer should not be destroyed if this is a "simple" LW.

2. If the component is HW:
At first, we retrieve the nearest heavyweight containers of both the oldContainer and the newContainer.
a) If the nearest HW containers are the same, we return the result of the !newHWContainer.isRestackSupported(). I.e. if the 'restack' operation is supported, there's no need to remove the peer.
b) If the HW containers differ: we return the result of the !comp.peer.isReparentSupported(), i.e. we check whether the component may safely be reparented.

The problem described at this CR actually happens at the step 1. In other words, we should handle a LW container having HW descendants just the same way as a regular HW component (just like, say, the HW/LW mixing code assumes, see CR 4811096 for more information).

The proposed fix changes the handling at the second step in the following way:
1. If the component is LW:
If it's not a Container or contains no HW descendants, the method returns false, meaning there's no need to destroy the peer. Otherwise proceed to the step 2.

2. If this point is reached, the component is either a regular HW, or a LW container with HW descendants. The handling of this case is performed in the old way. 

This successfully fixes the problem described at the Description. However, there's one concern left: we cannot be sure that it's correct to query the peer of a LW component about whether the "reparent" operation is supported as it happens at step 2-b). It seems that the support of the "reparent" operation should solely be the responsibility of the container (either the old one, or the new one, or even both). Only the operation itself should slightly depend on the kind of the component (we should either reparent the component itself if it's a HW, or should recursevely reparent all the HW descendants of the LW container we're currently reparenting).
Posted Date : 2007-08-07 10:14:07.0
Comments
  
  Include a link with my name & email   

Submitted On 03-AUG-2007
Overwriting the isLightweight() method of java.awt.Canvas seems to be a nice work around:

canvas = new Canvas() {
      public boolean isLightweight() {
        return true;
      }
    };



PLEASE NOTE: JDK6 is formerly known as Project Mustang