web-dev-qa-db-fra.com

java.lang.IllegalAccessError: tentative d'accès à la méthode

Je reçois une exception et je ne trouve pas la raison de celle-ci.

L'exception que je reçois est:

Java.lang.IllegalAccessError: tentative d'accès à la méthode Connected.getData (Ljava/lang/String;) Ljava/sql/ResultSet; de classe B

La méthode est publique.

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;
}

j'utilise Apache Tomcat 5.5.12 et Java 1.6

65
yossi

Vous utilisez presque certainement une version de la classe différente de celle attendue au moment de l'exécution. En particulier, la classe d'exécution serait différente de celle contre laquelle vous avez compilé (sinon, cela aurait causé une erreur de compilation) - cette méthode ever at-elle été private? Avez-vous d'anciennes versions des classes/jars sur votre système?

En tant que javadocs pour IllegalAccessError,

Normalement, cette erreur est interceptée par le compilateur. cette erreur ne peut se produire au moment de l'exécution que si la définition d'une classe a été modifiée de manière incompatible.

Je regarderais certainement votre chemin de classe et vérifierais qu'il réserve des surprises.

67
Andrzej Doyle

Cela se produit lors de l'accès à une méthode de package d'une classe appartenant au même package mais se trouvant dans un jar et un chargeur de classes différents. 

Ceci était ma source, mais le lien est maintenant brisé. Voici le texte intégral de Google Cache:

Les packages (comme dans l'accès aux packages) sont étendus par ClassLoader.

Vous indiquez que le ClassLoader parent charge l'interface et l'enfant ClassLoader charge l'implémentation. Cela ne fonctionnera pas à cause du Nature spécifique au ClassLoader de la portée du package. L’interface n’est pas visible pour la classe d'implémentation car, même s'il s'agit du même nom de package, ils sont dans différents ClassLoaders.

Je n'ai parcouru que les posts de ce fil de discussion, mais je pense que vous avez déjà découvert que cela fonctionnera si vous déclarez que l'interface est publique. Ce serait aussi travaillez pour que l'interface et l'implémentation soient chargées par le même ClassLoader.

Vraiment, si vous vous attendez à ce que des personnes arbitraires mettent en oeuvre l'interface (ce que vous faites apparemment si l'implémentation est chargée par un autre ClassLoader), vous devez alors rendre l'interface publique.

La portée de l'étendue du package par ClassLoader (qui s'applique à l'accès aux méthodes, variables, etc. du package. Package) est similaire à l'étendue générale de. noms de classe. Par exemple, je peux définir deux classes, toutes deux nommées com.foo.Bar, avec un code d'implémentation totalement différent si je les définis séparément ClassLoaders.

Joel

86
s_t_e_v_e

Si getData est protégé, essayez de le rendre public. Le problème pourrait exister dans Java 1.6 et être absent dans 1.5x 

J'ai ceci pour ton problème. Erreur d'accès illégal

5
Shadow

Je recevais cette erreur sur une application Spring Boot où un @RestController ApplicationInfoResource avait une classe imbriquée ApplicationInfo

Il semble que le Spring Boot Dev Tools utilisait un autre chargeur de classes.

L'exception que je devenais  

2017-05-01 17: 47: 39.588 WARN 1516 --- [nio-8080-exec-9] .m.m.a.ExceptionHandlerExceptionResolver: Une exception résolue a provoqué par exécution du gestionnaire: org.springframework.web.util.NestedServletException: répartition du gestionnaire échoué; L'exception imbriquée est Java.lang.IllegalAccessError: essayé de classe d'accès com.gt.web.rest.ApplicationInfo de la classe com.gt.web.rest.ApplicationInfoResource $$ EnhancerBySpringCGLIB $$ 59ce500c

Solution

J'ai déplacé la classe imbriquée ApplicationInfo dans un fichier .Java séparé et je me suis débarrassé du problème.

3
gtiwari333

Cela m'est arrivé quand une classe dans un bocal essayait d'accéder à une méthode privée dans une classe à partir d'un autre bocal. J'ai simplement changé la méthode privée en publique, recompilée et déployée, et cela a fonctionné correctement par la suite.

2
Alan Smith

Juste un ajout à la réponse résolue:

Cela pourrait poser un problème avec la fonction d'exécution instantanée d'Android Studio, par exemple, si vous réalisez que vous avez oublié d'ajouter la ligne de code: finish() à votre activité après en avoir ouvert une autre, et que vous avez déjà rouvert l'activité Si vous n'avez pas rouvert (que le finish() a résolu), vous ajoutez ensuite finish() et Instant Run se produit, puis l'application se bloque, car la logique a été interrompue. 


TL: DR;

Ce n'est pas nécessairement un problème de code, juste un problème d'exécution instantanée

0
Ab_

Du point de vue Android: Méthode non disponible dans la version api

J'obtenais ce problème principalement parce que j'utilisais quelque chose qui n'est pas disponible/obsolète dans cette version Android

Fausse route:

Notification.Builder nBuilder = new Notification.Builder(mContext);
nBuilder.addAction(new Notification.Action(Android.R.drawable.ic_menu_view,"PAUSE",pendingIntent));

La bonne façon:

Notification.Builder nBuilder = new Notification.Builder(mContext);
nBuilder.addAction(Android.R.drawable.ic_media_pause,"PAUSE",pendingIntent);

ici Notification.Action n'est pas disponible avant API 20 et ma version minimale était API 16.

0
Maurice

Dans mon cas, le problème était qu’une méthode était définie dans une interface A comme default, alors que sa sous-classe l’avait surchargée comme privée. Ensuite, lorsque la méthode a été appelée, Java Runtime s'est rendu compte qu'il appelait une méthode privée.

Je ne comprends toujours pas pourquoi le compilateur ne s'est pas plaint du remplacement privé.

public interface A {
     default void doStuff() {
         // doing stuff
     }
}

public class B {
     private void doStuff() {
         // do other stuff instead
     }
}

public static final main(String... args) {
    A someB = new B();
    someB.doStuff();
}
0
Lonely Neuron