Programmation Java/Débogage
Outils de débogage
[modifier | modifier le wikicode]Pour déboguer sans TDD (test driven development), on peut ajouter le code suivant où l'on veut :
System.out.println("Valeur à afficher");System.exit(0);
Cependant ce n'est pas la meilleure façon de faire. Il est préférable d'utiliser un IDE supportant le débogage :
- Poser des points d'arrêt pour suspendre l'exécution et inspecter les valeurs des attributs, des arguments, des variables locales.
- Reprendre ensuite en mode pas à pas pour voir l'évolution des valeurs et voir quelle partie du code s'exécute.
Par exemple, Eclipse possède deux manières de lancer une application :
- Le bouton de lancement normal ignore tous les points d'arrêts.
- Le bouton de débogage représenté par une icône d'insecte pour le mot anglais "bug" (cafard), permet de prendre en compte les points d'arrêt pour suspendre l'exécution de l'application. Une perspective spécifique au débogage est alors affichée pour lister les expressions à pister et voir le code source.
VisualVM
[modifier | modifier le wikicode]VisualVM est un outil permettant d'explorer les informations sur les machines virtuelles Java qui tournent sur la machine (une JVM par application).
Cet outil était disponible avec la plateforme Java, édition standard (Java SE) dans les versions du JDK de la version 6 (update 7) jusqu’à la version 8 incluse (voir https://docs.oracle.com/javase/8/docs/technotes/guides/visualvm/). Il est désormais disponible séparément sur le site https://visualvm.github.io/ .
jdb
[modifier | modifier le wikicode]jdb est un débogueur en ligne de commande fourni avec le JDK.
- Pour plus de détails voir : Programmation Java/JDK#jdb.
Erreurs à la compilation
[modifier | modifier le wikicode]Fenêtre de warning ...java uses unchecked or unsafe operations
[modifier | modifier le wikicode]Une déclaration ne tient pas compte des surcharges possibles, une conversion de variable pose problème. Il faut donc en prévoir les exceptions. Par exemple pour manipuler des entiers :
try {
i = i/2;
} catch (NumberFormatException e) {
return 0;
}
<identifier> expected
[modifier | modifier le wikicode]L'ordre des déclarations n'est pas chronologique.
annotation type not applicable to this kind of declaration
[modifier | modifier le wikicode]Voir @Override.
cannot be dereferenced
[modifier | modifier le wikicode]- Il suffit de retirer la conversion, le .toString() après la variable de type int sélectionnée.
- Ou en ajouter une comme : (float), Float.valueOf(), ou .floatValue().
cannot find symbol - variable
[modifier | modifier le wikicode]Soit :
- La variable mentionnée n'a pas été déclarée (ou elle a été mal écrite) ;
- Sa déclaration trouve dans une condition (
ifoutry) fermée avant la ligne en erreur ; - Elle se trouve dans un package non importé ;
- Si elle se trouve dans un autre fichier, les compiler depuis leur répertoire parent commun (les IDE le font automatiquement) :
javac Projet1/Classe1.java
javac Projet1/Classe2.java
cannot instantiate from arguments because actual and formal argument lists differ in length
[modifier | modifier le wikicode]Cela peut survenir suite à un Collections.sort(liste), alors même que le Collections.shuffle(liste) fonctionne. Il faut donc utiliser import java.util.Comparator; dans le trie :
import java.util.Collections;
import java.util.Comparator;
...
private List<T> list;
private Comparator<T> comparator = null;
if(this.comparator!= null) {
Collections.sort(list, comparator);
}
constructor variable in class classe cannot be applied to given types
[modifier | modifier le wikicode]Les paramètres du constructeur n'ont pas le bon type.
- Vérifier les paramètres de l'appel au constructeur ;
- Si besoin ajouter un nouveau constructeur supportant les types d'arguments utilisés.
exception IOException is never thrown in body of corresponding try statement
[modifier | modifier le wikicode]Un try inutile a été détecté.
Cela peut être causé par la mise en commentaires de lignes devenues inutiles (instructions de débogage par exemple).
impossible de trouver la classe principale
[modifier | modifier le wikicode]- Lancer la commande "java" vers un .class (et non un .java).
- Ajouter le chemin vers le
packageracine des.classdans leclasspath. - Exécuter une classe comportant la méthode statique
maincomme ci-dessous. - Vérifier que la déclaration de la méthode statique
mainest conforme à ci-dessous.
public static void main(String[] args)
{
//...
}
incompatible types: possible lossy conversion from float to int ou double to float
[modifier | modifier le wikicode]Il faut passer une conversion de format :
java.text.DecimalFormat df = new java.text.DecimalFormat("#");
monFloat = Float.valueOf(df.format(monDouble));
local variable referenced from a lambda expression must be final or effectively final
[modifier | modifier le wikicode]Une expression lambda référençant une variable locale peut être appelée après changement de la valeur de la variable. Il faut :
- soit ajouter
finalà la variable locale ou à l'argument de méthode utilisé, - soit déclarer une nouvelle variable
finalinitialisée avec la valeur de la variable locale.
local variable ma_variable is accessed from within inner class; needs to be declared final
[modifier | modifier le wikicode]Une classe interne référençant une variable locale peut être utilisée après changement de la valeur de la variable. Il faut :
- soit ajouter
finalà la variable locale ou à l'argument de méthode utilisé, - soit déclarer une nouvelle variable
finalinitialisée avec la valeur de la variable locale.
no suitable method found for - méthode
[modifier | modifier le wikicode]La méthode mentionnée n'a pas été déclarée, ou du moins pas avec ce type de paramètre (ex : remplacer .addAll() par .add()).
no suitable constructor found for Integer(double)
[modifier | modifier le wikicode]Convertir plus explicitement :
MonEntier = ((Number)MonDouble).intValue();
no suitable constructor for classe is abstract cannot be instanciated
[modifier | modifier le wikicode]S'il est possible de retirer le mot abstract de la déclaration de la classe, le faire.
Sinon, instancier une sous-classe qui implémente les méthodes manquantes.
non-static method/variable ... cannot be referenced from a static context
[modifier | modifier le wikicode]Cela peut se produire en invoquant une méthode ou une variable d'instance (membre non statique) depuis une méthode statique ou une classe interne statique.
- Si elle est bien statique :
- Au sein de la même classe, retirer le
this.en préfixe. - Depuis une autre classe, ajouter le nom de la classe en préfixe.
- Sinon, il faut rendre la variable appelée dans la méthode statique, statique aussi.
- Au sein de la même classe, retirer le
- Si elle n'est pas statique :
- On peut rendre la méthode statique non statique.
- Sinon, ajouter ou remplacer le "this." par le nom de la variable désignant la classe (ex : "c.") :
MaClasse c = new MaClasse();
c.MaMethode();
not a statement
[modifier | modifier le wikicode]Il manque sûrement les parenthèses après le nom d'une méthode.
reference to assertequals is ambiguous
[modifier | modifier le wikicode]Il convient d'assurer un typage plus fort des paramètres de assertequals(), par exemple avec .intValue().
unclosed character literal
[modifier | modifier le wikicode]Il manque le délimiteur apostrophe final, ou bien l'apostrophe comme caractère doit être préfixée d'un anti-slash.
Ou bien utiliser une chaîne de caractères pour zéro ou plus d'un caractère.
unclosed string literal
[modifier | modifier le wikicode]Il manque le délimiteur guillemet final, ou bien le guillemet comme caractère dans la chaîne doit être préfixé d'un anti-slash.
unreachable statement
[modifier | modifier le wikicode]Une partie de code ne sera jamais exécutée, parce qu'elle est juste après break, return ou throw.
unreported exception ...; must be caught or declared to be thrown
[modifier | modifier le wikicode]Une exception est lancée explicitement (throw new NomDeTException("Message");) ou par une méthode déclarant pouvoir lancer cette exception sans que la méthode appelante ait déclarée avec throws NomDeLException.
- Soit il faut ajouter une capture de l'exception dans la méthode si elle peut la traiter complétement à son niveau (journalisation, message à l'utilisateur, arrêter une procédure en cours...),
- Soit plus probablement il faut que la méthode déclare lancer ce type d'exception avec le mot-clé
throwsà la fin de la déclaration de la méthode.
Il se peut que la méthode puisse traiter partiellement l'exception (ex : journaliser l'erreur) et qu'elle doive la relancer pour qu'elle soit traitée complétement ailleurs (remonter jusqu'au code de l'interface graphique pour l'affichage d'un message d'erreur). Dans ce cas, un mélange des deux solutions est à faire :
- Capturer l'exception pour journaliser l'erreur et la relancer avec
throw - Déclarer ce type d'exception avec le mot-clé
throwsà la fin de la déclaration de la méthode.
variable is already defined
[modifier | modifier le wikicode]Une variable avec un nom identique existe déjà dans la portée (scope) de la ligne indiquée.
Exemple :
switch (args[0].toString())
{
case "1":
int a = 1;
//...
break;
case "2": // Même portée que case "1"
int a = 2;
//...
break;
}
Il faut :
- soit renommer la variable,
- soit réutiliser la variable précédente :
switch (args[0].toString())
{
case "1":
int a = 1;
//...
break;
case "2": // Même portée que case "1"
a = 2; // Réutilisation de a
//...
break;
}
- soit utiliser des portées différentes pour chaque cas avec les accolades :
switch (args[0].toString())
{
case "1":
{
int a = 1;
//...
}
break;
case "2":
{
int a = 2;
//...
}
break;
}
variable might not have been initialized
[modifier | modifier le wikicode]Il faut assigner une valeur par défaut à l'objet. Ex :
String[] a = {"", ""};
BufferedWriter bw = null;
Erreurs à l'exécution
[modifier | modifier le wikicode]Si deux variables de type String identiques ne peuvent pas être comparées
[modifier | modifier le wikicode]L'opérateur == vérifie les références au lieu du contenu.
Il faut donc utiliser la méthode .equals().
String s = "test";
StringBuffer sb = new StringBuffer("test");
System.out.println(s == new String(sb)); // false !
System.out.println(s.equals(new String(sb))); // true :)
Si une division fait toujours 0.0
[modifier | modifier le wikicode]Ajouter (double) ou (float) devant l'un des opérateur de la division pour forcer le calcul en nombre à virgule flottante.
NullPointerException
[modifier | modifier le wikicode]Exception levée quand une référence nulle (null) est utilisée comme objet pour accéder à un membre : appeler une méthode, lire ou écrire un champ, obtenir une référence de sous-classes d'instance...
La correction dépend de l'intention voulue. Par exemple, si des paramètres incorrectes conduisent à la production de l'exception, c'est un moyen de propager un problème important, L'exception de propage d'appelant en appelant jusqu'au traitement de l'exception par une méthode appelante :
try
{
// ...
}
catch (NullPointerException npe)
{
// traiter l'exception:
// - En mode debug, afficher la pile d'appel dans la console pour débogger : npe.printStackTrace();
// - En mode release, ajouter un message d'erreur dans un fichier de log
// - Signaler l'erreur à l'utilisateur et lui redemander des valeurs correctes
}
aucun attribut manifest principal dans ...jar
[modifier | modifier le wikicode]Il n'y a pas de méthode main() dans le .jar, ce fichier ne peut donc pas être exécuté directement, mais peut être utilisé par une application ayant une méthode main().
Class names, classe, are only accepted if annotation processing is explicitly requested
[modifier | modifier le wikicode]Les classes définies à la compilation (par exemple avec javac -classpath) sont introuvables.
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 1
[modifier | modifier le wikicode]Un des tableaux de la ligne indiquée est appelé avec un indice négatif, ou supérieur ou égal à sa taille.
Il peut s'agir d'une exception volontairement levée en cas de problème avec les données d'entrée. Voir NullPointerException pour le traitement d'erreur.
La classe ArrayIndexOutOfBoundsException étant une sous-classe de RuntimeException n'a pas besoin de déclaration throws sur les méthodes.
Cela signifie que toute méthode utilisant des tableaux peut la lancer.
java.lang.ArithmeticException: / by zero
[modifier | modifier le wikicode]Une division par zéro s'évite généralement par un if sur le dénominateur, ou un throw d'une exception.
java.lang.NumberFormatException
[modifier | modifier le wikicode]Le contenu d'une chaîne de caractère ne peut être interprétée comme un nombre :
- Soit à cause d'un symbole qui n'est pas un chiffre (ex : €)
- ou bien une virgule à la place d'un point pour un nombre réel.
Stream closed
[modifier | modifier le wikicode]Retirer le .close() de la boucle du .read() ou du .write(), même s'il est situé après. Si cela ne suffit pas, le retirer de la méthode.
Unable to load native library: Can't load IA 32-bit .dll on a AMD 64-bit platform
[modifier | modifier le wikicode]Une application utilisant du code natif a tenté de chargé une bibliothèque de code dynamique (.dll sous windows, .so sous Linux/Mac) 32 bit sur une machine virtuelle Java 64 bits. L'inverse provoque également une variante de ce message d'erreur.
Solutions possibles :
- Installer la version 32 ou 64 bits du JRE requise.
- Ou chercher une version de l'application ayant une bibliothèque de code dynamique adaptée à la JVM 32 ou 64 bits.
Une application Java utilisant du code natif bien conçue ne devrait jamais rencontrer ce problème : il est possible de détecter la version de Java (32 ou 64 bits) avant de charger la bibliothèque dynamique appropriée, ce qui signifie avoir une version 32 bits et une version 64 bits de cette bibliothèque dynamique (ex : mylib-32.dll et mylib-64.dll).
