Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 306609

Summary: EventDispatcher#getFocusOwner protected visibility leads to verify error
Product: [Tools] GEF Reporter: Jens Von Pilgrim <developer>
Component: GEF-Legacy Draw2dAssignee: Anthony Hunter <ahunter.eclipse>
Status: RESOLVED FIXED QA Contact:
Severity: blocker    
Priority: P3 CC: ahunter.eclipse, heiko.boettger, remy.suen
Version: 3.6   
Target Milestone: 3.6.0 (Helios) RC1   
Hardware: All   
OS: All   
Whiteboard:
Bug Depends on: 241767    
Bug Blocks:    
Attachments:
Description Flags
Simplified projects reproducing the error none

Description Jens Von Pilgrim CLA 2010-03-20 15:30:05 EDT
In rev. 1.14, Anthony Hunter changed the visibility of EventDispatcher#getFocusOwner() from package visible to protected. While this change makes it possible to create subclasses in other packages, it disables calls to getFocusOwner() from other instances (Bad access to protected data). The latter case occurs in delegating classes, as we have it implemented in GEF3D. In GEF3D, we wrap the original EventDispatcher into a 3D version. The 3D version delegates calls to getFocusOwner() to the wrapped 2D version -- which is now no longer possible. Actually, this was already a hack, as we had to place our 3D version into a package o.e.gef (instead of o.e.gef3d). We already filed a bug report about that: https://bugs.eclipse.org/bugs/show_bug.cgi?id=281008

Actually, this is a blocker for the GEF3D project! As written in bug #281008, I'd suggest to simply make all methods public in EventDispatcher (or even better: make EventDispatcher an interface).

Jens
Comment 1 Remy Suen CLA 2010-03-20 17:48:26 EDT
I had the same problem when I was trying to run GEF3D on e4. Changing the GEF3D variant's method to be protected didn't help (well, it fixed the compiler error anyway). When I made the originating method in EventDispatcher public then the VerifyError went away.
Comment 2 Anthony Hunter CLA 2010-03-20 19:39:38 EDT
ok, will investigate a solution in 3.6 M7.
Comment 3 Jens Von Pilgrim CLA 2010-03-31 14:33:04 EDT
Created attachment 163558 [details]
Simplified projects reproducing the error

I tried to reproduce the error with simplified Java classes. I finally found the problem (thanks to http://www.coderanch.com/forums/forums/posts/watch/0/328067 ): It's the classloaders. 

I have attached an archive with two simple projects: APlugin (=draw2D) and BPlugin (=draw3d). This is the overall structure:

APlugin: A.java:
    package a;
    
    public class A { // = EventDispatcher
        protected void m() { // = getFocusOwner()
        };
    }

BPlugin: B.java
    package a;
    
    public class B extends A { // = EventDispatcher3D
        private A x;
    
        public B(A x) {
            this.x = x;
        }
    
        @Override
        protected void m() {
            x.m();
        }
    }        
    
BPlugin contains a view (in order to get loaded). In its activator, you'll find the following code:

    public Activator() {
		new B(new A()); // got you!
	}    
	
This is where the error occurs:

Caused by: java.lang.VerifyError: (class: a/B, method: m signature: ()V) Bad access to protected data
at bplugin.Activator.<init>(Activator.java:24)

As explained by Ernest Friedman-Hill (see URL above) the problem is, that two packages with the same name are in fact different when loaded with different class loaders. From the VM spec (http://java.sun.com/docs/books/jvms/second_edition/html/ConstantPool.doc.html):

"R is either protected or package private (that is, neither public nor protected nor private), and is declared by a class in the same runtime package as D."

Apparently, package and runtime package are different. Frankly, I'm not a VM expert. What confuses me most is, that it's all working with package visibility, because this should apply to the very same "rule", should it?

I admit that we are using a dirty hack in Draw3D by defining the same package as in Draw2D. Anyway, we absolutely need the EventDispatcher class to be publicly accessible and subclassable (or at least from outside Draw2D).
Comment 4 Anthony Hunter CLA 2010-04-01 12:00:53 EDT
(In reply to comment #3)
> I admit that we are using a dirty hack in Draw3D by defining the same package
> as in Draw2D. Anyway, we absolutely need the EventDispatcher class to be
> publicly accessible and subclassable (or at least from outside Draw2D).

Are you planning on fixing this hack? You guys did not do a release of Draw3D with org.eclipse.draw2d packages did you?

Anyway, I will look and see if we can make the methods public.
Comment 5 Jens Von Pilgrim CLA 2010-04-01 13:07:07 EDT
> Are you planning on fixing this hack? 

OK, GEF3D itself is a kind of hack ;-) IMHO it's impossible to create something like GEF3D without some hacks... (at least when a framework uses non-public access). But seriously, we absolutely rely on that specific hack as we need to replace the EventDispatcher with a 3D version. 

Actually, there are some other dirty things, too, and I already reported some of these issues (https://bugs.eclipse.org/bugs/show_bug.cgi?id=278559, https://bugs.eclipse.org/bugs/show_bug.cgi?id=290531), some more issues are GMF related. I didn't added more bugs because these bug reports were ignored so far (except this bug, which I marked as a blocker).  

In general I'm wondering why so much methods (and fields with no public/protected accessors) are private or package visible only. Fortunately, EventDispatcher is the only case in which we were forced to "camouflage" our classes with a foreign package name. 

Other problems of that type:
- org.eclipse.draw2d.FreeformHelper, we duplicated the code simply because FreeformHelper is package visible only... 
- org.eclipse.draw2d.MouseEvent has a package visible constructor only. Fortunately we do not need that constructor in Draw3D anymore, but it was a blocker in a predecessor version of GEF3D in which I used Java3D (which is AWT based, that is, I needed to create such a MouseEvent in order to propagate the AWT events to Draw2D).
Do you think I should file bug reports about these issues (that is, is there a chance these things get changed?)

> You guys did not do a release of Draw3D with org.eclipse.draw2d packages did you?

No, we didn't release Draw3D yet, since there is no release of GEF3D at all (I planned to create a release including JOGL, but unfortunately JOGL is under IP review for more than a year now, but that's a different issue).

> Anyway, I will look and see if we can make the methods public.

That would be great!

Cheers,

Jens
Comment 6 Anthony Hunter CLA 2010-05-03 13:10:23 EDT
We released 3.6 M7 today so moving unresolved bugs to 3.6 RC1.

We need to re-access if we can complete these for Helios.
Comment 7 Anthony Hunter CLA 2010-05-17 10:31:09 EDT
I fixed the method we changed in M6 to public. Can you confirm this is sufficient?
Comment 8 Anthony Hunter CLA 2010-05-17 15:19:38 EDT
(In reply to comment #7)
> I fixed the method we changed in M6 to public. Can you confirm this is
> sufficient?

Reopen if not.
Comment 9 Jens Von Pilgrim CLA 2010-05-18 06:57:04 EDT
It's working, thank you very much!