问题描述
几乎可以肯定,您在运行时使用的类版本与您期望的版本不同。特别是,运行时类将不同于您针对其进行编译的类(否则将导致编译时错误)-该方法曾经存在private吗?您的系统上任何地方都有类/ jar的旧版本吗?
作为IllegalAccessError
状态的javadocs ,
通常,此错误是由编译器捕获的。如果类的定义发生了不兼容的更改,则只有在运行时才会发生此错误。
我一定会看看您的类路径,并检查它是否有任何惊喜。
当访问在同一包中但在不同的jar和类加载器中的类的包范围方法时,会发生这种情况。
这是我的消息来源,但是链接现在断开了。以下是Google缓存的全文:
包(在包访问中)按ClassLoader进行作用域限定。
您声明父ClassLoader加载接口,子ClassLoader加载实现。由于软件包作用域的特定于ClassLoader的性质,因此无法使用。实现类看不到该接口,因为即使它具有相同的包名称,它们也位于不同的ClassLoader中。
我只浏览了该线程中的帖子,但我认为您已经发现,如果您声明接口为公共,则可以使用。使接口和实现都由同一个ClassLoader加载也将起作用。
的确,如果您希望任意的人来实现该接口(如果实现是由其他ClassLoader加载的,那么您显然会这样做),则应该将该接口公开。
包作用域的ClassLoader作用域(适用于访问包方法,变量等)类似于类名的常规ClassLoader作用域。例如,如果我在单独的ClassLoader中定义它们,则可以使用完全不同的实现代码来定义两个都命名为com.foo.Bar的类。
解决方法
我遇到了一个例外,但找不到原因。
我得到的例外是:
java.lang.IllegalAccessError
:尝试访问方法Connected.getData(Ljava / lang / String;)Ljava / sql / ResultSet
; 从B类
该方法是公开的。
public class B
{
public void myMethod()
{
Connected conn = new Connected(); // create a connected class in order to connect to The DB
ResultSet rs = null; // create a result set to get the query result
rs = conn.getData(sql); // do sql query
}
}
public class Connected
{
public ResultSet getData(String sql)
{
ResultSet rs = null;
try
{
prepareConnection();
stmt = conn.createStatement();
stmt.execute(sql);
rs = stmt.getResultSet();
}
catch (SQLException E)
{
System.out.println("Content.getData Error");
E.printStackTrace();
}
return rs;
}
我正在使用Tomcat 5.5.12和JAVA 1.6