Java 中的非法訪問錯誤

1. 概述

在這個快速教程中,我們將討論java.lang.IllegalAccessError

我們將研究一些關於何時拋出以及如何避免它的示例。

2. IllegalAccessError

當應用程序嘗試訪問字段或調用不可訪問的方法時,會引發IllegalAccessError

編譯器會捕獲此類非法調用,但我們仍可能在運行時IllegalAccessError

首先,讓我們觀察一下IllegalAccessError:

java.lang.Object

 |_java.lang.Throwable

 |_java.lang.Error

 |_java.lang.LinkageError

 |_java.lang.IncompatibleClassChangeError

 |_java.lang.IllegalAccessError

它的父類是IncompatibleClassChangeError.因此,此錯誤的原因是應用程序中一個或多個類定義的不兼容更改。

簡而言之,運行時類的版本與其編譯時所針對的版本不同。

3. 這個錯誤怎麼會發生?

讓我們用一個簡單的程序來理解這一點:

public class Class1 {

 public void bar() {

 System.out.println("SUCCESS");

 }

 }



 public class Class2 {

 public void foo() {

 Class1 c1 = new Class1();

 c1.bar();

 }

 }

在運行時,上面的代碼調用Class1. bar()到現在為止還挺好。

現在,讓我們將bar()的訪問修飾符更新為private並獨立編譯它。

接下來,將Class1 (the .的先前定義(.class 文件)替換為新編譯的版本並重新運行程序:

java.lang.IllegalAccessError:

 class Class2 tried to access private method Class1.bar()

上述例外是不言自明的。方法bar()現在在Class1. private顯然,訪問是非法的。

4. IllegalAccessError在行動

4.1.圖書館更新

考慮一個在編譯時使用庫的應用程序,並且在運行時在類路徑中也可用。

庫所有者將公開可用的方法更新為私有,重建它,但忘記更新此更改的其他方。

此外,在執行時,當應用程序調用此方法(假設公共訪問)時,它會遇到IllegalAccessError.

4.2 接口默認方法

接口中默認方法的濫用是導致此錯誤的另一個原因。

考慮以下接口和類定義:

interface Baeldung {

 public default void foobar() {

 System.out.println("This is a default method.");

 }

 }



 class Super {

 private void foobar() {

 System.out.println("Super class method foobar");

 }

 }

另外,讓我們擴展Super並實現Baeldung:

class MySubClass extends Super implements Baeldung {}

最後,讓我們通過實例化MySubClass: foobar()

new MySubClass().foobar();

方法foobar() Super是私有的,在Baeldung. default因此,它可以在 MySubClass 的層次結構中MySubClass.

因此,編譯器不會抱怨,但在運行時,我們得到一個錯誤:

java.lang.IllegalAccessError:

 class IllegalAccessErrorExample tried to access private method 'void Super.foobar()'

在執行期間,超類方法聲明始終優先於接口默認方法。

從技術上講, Super foobar ,但它是私有的。毫無疑問,會拋出IllegalAccessError

5. 如何避免?

準確地說,如果我們遇到IllegalAccessError ,我們應該主要尋找類定義中關於訪問修飾符的變化。

其次,我們應該驗證被私有訪問修飾符覆蓋的接口默認方法。

將類級別的方法設為公開即可。

六,結論

總而言之,編譯器將解決大多數非法方法調用。如果我們仍然遇到IllegalAccesError ,我們需要查看類定義的變化。