1. Overview
1.概述
In this quick tutorial, we’ll discuss the java.lang.IllegalAccessError.
在这个快速教程中,我们将讨论java.lang.IllegalAccessError。
We’ll examine some examples of when it is thrown and how to avoid it.
我们将研究一些抛出的例子,以及如何避免它。
2. Introduction to IllegalAccessError
2.介绍IllegalAccessError
An IllegalAccessError is thrown when an application attempts to access a field or invoke a method that is inaccessible.
IllegalAccessError被抛出当一个应用程序试图访问一个字段或调用一个无法访问的方法时,。
The compiler catches such illegal invocations, but we may still bump into an IllegalAccessError at runtime.
编译器会捕捉到这样的非法调用,但我们在运行时仍可能会遇到IllegalAccessError。
First, let’s observe the class hierarchy of IllegalAccessError:
首先,让我们观察一下IllegalAccessError的类的层次结构:。
java.lang.Object
|_java.lang.Throwable
|_java.lang.Error
|_java.lang.LinkageError
|_java.lang.IncompatibleClassChangeError
|_java.lang.IllegalAccessError
Its parent class is IncompatibleClassChangeError. Hence, the cause of this error is an incompatible change in one or more class definitions in the application.
它的父类是IncompatibleClassChangeError。因此,这个错误的原因是应用程序中的一个或多个类定义发生了不兼容的变化。
Simply put, the version of the class at runtime is different from the one it was compiled against.
简单地说,运行时的类的版本与它被编译的版本不同。
3. How May This Error Occur?
3.这个错误是如何发生的?
Let’s understand this with a simple program:
让我们通过一个简单的程序来理解这一点。
public class Class1 {
public void bar() {
System.out.println("SUCCESS");
}
}
public class Class2 {
public void foo() {
Class1 c1 = new Class1();
c1.bar();
}
}
At runtime, the above code invokes the method bar() in Class1. So far, so good.
在运行时,上述代码调用了Class1中的bar()/em>方法。到目前为止,一切都很好。
Now, let’s update the access modifier of bar() to private and independently compile it.
现在,让我们把bar()的访问修饰符更新为private,并独立编译它。
Next, replace the previous definition of Class1 (the .class file) with the newly compiled version and re-run the program:
接下来,用新编译的版本替换之前的Class1(.class文件)的定义,并重新运行程序。
java.lang.IllegalAccessError:
class Class2 tried to access private method Class1.bar()
The above exception is self-explanatory. The method bar() is now private in Class1. Clearly, it’s illegal to access.
上面的异常是不言自明的。方法bar()现在在Class1中是private。很明显,它的访问是非法的。
4. IllegalAccessError in Action
4.IllegalAccessError的行动
4.1. Library Updates
4.1.图书馆更新
Consider an application that uses a library at compile-time, and the same is also available in classpath during runtime.
考虑到一个应用程序在编译时使用一个库,并且在运行时也可以在classpath中使用。
The library owner updates a publicly available method to private, rebuilds it, but forgets to update other parties of this change.
库的所有者将一个公开可用的方法更新为私有的,并重建了它,但却忘了向其他各方更新这一变化。
Furthermore, while executing, when the application invokes this method (assuming public access), it runs into an IllegalAccessError.
此外,在执行过程中,当应用程序调用这个方法时(假设是公共访问),会遇到一个IllegalAccessError.。
4.2. Interface Default Methods
4.2.接口默认方法
Misuse of default methods in Interfaces is another cause of this error.
滥用Interfaces中的default方法是造成这种错误的另一个原因。
Consider the following interface and class definitions:
请考虑以下接口和类的定义。
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");
}
}
Also, let’s extend Super and implement Baeldung:
另外,让我们扩展Super并实现Baeldung:。
class MySubClass extends Super implements Baeldung {}
Finally, let’s invoke foobar() by instantiating MySubClass:
最后,让我们通过实例化MySubClass:来调用foobar()。
new MySubClass().foobar();
The method foobar() is private in Super and default in Baeldung. Hence, it is accessible in the hierarchy of MySubClass.
方法 foobar()在Super中是私有的,在Baeldung中是default。因此,它在MySubClass的层次结构中可以被访问。
Therefore, the compiler doesn’t complain, but at runtime, we get an error:
因此,编译器没有抱怨,但在运行时,我们得到一个错误。
java.lang.IllegalAccessError:
class IllegalAccessErrorExample tried to access private method 'void Super.foobar()'
During execution, a super-class method declaration always takes priority over an interface default method.
在执行过程中,超类方法声明总是优先于接口默认方法。
Technically, foobar from Super should have been called, but it’s private. Undoubtedly, an IllegalAccessError will be thrown.
技术上讲,Super的foobar应该被调用,但它是私有的。毫无疑问,一个IllegalAccessError将被抛出。
5. How to Avoid It?
5.如何避免它?
Precisely, if we run into an IllegalAccessError, we should primarily look for changes in the class definitions with respect to access modifiers.
准确地说,如果我们遇到IllegalAccessError,我们应该主要寻找类定义中有关访问修改器的变化。
Secondly, we should validate interface default methods overridden with a private access modifier.
其次,我们应该验证用私有访问修饰符覆盖的接口默认方法。
Making the class-level method public will do the trick.
把类级方法变成公共的就可以了。
6. Conclusion
6.结语
To conclude, the compiler will resolve most of the illegal method invocations. If we still come across an IllegalAccesError, we need to look into class definition changes.
总而言之,编译器会解决大部分的非法方法调用的问题。如果我们仍然遇到IllegalAccesError,我们需要研究类定义的变化。
The source code of the examples is available over on GitHub.
例子的源代码可在GitHub上获得。