2011-04-09 23 views
5

對AbstractDocument.UndoRedoDocumentEvent的instanceof試圖在javax.swing.text.DefaultCaret.Handler.insertUpdate(DocumentEvent)來源時,我發現下面的線(始於1685線):IllegalAccessError從javax.swing.text中

if (e instanceof AbstractDocument.UndoRedoDocumentEvent) { 
    setDot(offset + length); 
    return; 
} 

但當我嘗試這個辦法:

package javax.swing.text; 

public class Foo { 
    public static void main(String[] args) { 
     Object o = new Object(); 
     if (o instanceof AbstractDocument.UndoRedoDocumentEvent) { 
      System.out.println("yay"); 
     } else { 
      System.out.println("aww"); 
     } 
    } 
} 

它會給:

Exception in thread "main" java.lang.IllegalAccessError: tried to access class javax.swing.text.AbstractDocument$UndoRedoDocumentEvent from class javax.swing.text.Foo 
    at javax.swing.text.Foo.main(Foo.java:6) 

爲什麼我不能instanceof反對那個班,但DefaultCaret.Handler可以嗎?

使用Java版本1.6.0_20

$ java -version 
java version "1.6.0_20" 
OpenJDK Runtime Environment (IcedTea6 1.9.7) (6b20-1.9.7-0ubuntu1~10.04.1) 
OpenJDK Client VM (build 19.0-b09, mixed mode, sharing) 

UPDATE:

基於答案我試過如下:

文件Foo.java

package javax.swing.text; 

public class Foo { 
    public static void main(String[] args) { 
     Object o = new Object(); 
     if (o instanceof Outer.Inner) { 
      System.out.println("yay"); 
     } else { 
      System.out.println("aww"); 
     } 
    } 
} 

文件Outer.java

package javax.swing.text; 

public class Outer { 
    class Inner { 
    } 
} 

這工作得很好,並打印 「噢」 的預期。

請注意,這兩個文件都在包javax.swing.text中。還請注意,Foo.java已經在我原始問題中的包javax.swing.text中。

據我可以告訴包是不是「密封」。清單rt.jar(包含包javax.swing.text的清單)不包含「密封」。命令Package.getPackage("javax.swing.text").isSealed()返回false。

所以我可以instance of針對我自己的內部類,但不是針對AbstractDocument.UndoRedoDocumentEvent,即使包中的其他類也可以。

任何想法爲什麼這樣?

回答

3

看起來UndoRedoDocument是包保護,並DefaultCaret.HandlerUndoRedoDocument是在同一包(javax.swing.text如果我沒有記錯)。

1

第一個想法是包javax.swing.text是封閉的,並且您不允許向它添加新的類。您的包裝是否也會發生同樣的情況?


編輯: 從我的評論:

有點晚了,但我認爲一個原因可能是你的類和搖擺類是由不同的類加載器和包裝 從不同的類加載器加載不是 被認爲是相同的包,即使它們具有相同的名稱。

您可以看看Name.class.getClassLoader()object.getClass().getClassLoader()使用了哪個類裝入器。打印這些。 (這可能是擺動類的ClassLoader是null,表示引導類加載器(由虛擬機實現的,加載ClassClassLoader類之前創建的)。您的應用程序的類加載器很可能另一個。

使用你自己的類加載器創建一個類,使用一個URLClassLoader,它應該讓你的應用程序的類加載器作爲父類(允許類彼此訪問),但是使用另一個URL(例如,加載類未加載。常見的類路徑)

你可以做這樣的事情:

  • 將您的Outer類放在應用程序的類路徑中。
  • 創建一個主類(在相同的類路徑)是這樣的:

    class Main { 
        public static void main(String[] ignored) throws Exception { 
         URL url = new URL("file:///path/to/other/dir"); 
         ClassLoader cl = new URLClassLoader(url, Main.class.getClassLoader()); 
         Class<?> testClass = cl.loadClass("package.Test"); 
         testClass.getMethod("test").invoke(null); 
        } 
    } 
    
  • 在相同的封裝外創建測試類這樣的,但在主類在URL根:

    class Test { 
        public static void test() { 
         Object o = new Object(); 
         if (o instanceof Outer.Inner) { 
          System.out.println("yay"); 
         } else { 
          System.out.println("aww"); 
        } 
        } 
    } 
    

如果我的理論是正確的,這應該給同一類型的異常。 (我沒有嘗試。)

+0

我嘗試使用我自己的類(和內部類),它的工作。該包似乎並沒有被封印。我用更多的信息更新了這個問題。 – lesmana 2011-04-09 19:29:45

+0

有點晚了,但我認爲一個原因可能是你的類和swing類是由不同的類加載器加載的,並且從不同的類加載器加載的包不被認爲是相同的包,即使它們具有相同的名稱。 – 2011-06-12 15:37:19

+0

ŭloEbermann:不算太晚。我仍然對答案感興趣。是否有可能檢查哪個類加載了哪個類加載器?如果你解釋瞭如何使用兩個不同的類加載器來使用自制類來重現錯誤消息,那麼獎勵點。這將證明你的假設。 – lesmana 2011-06-12 21:49:29

相關問題