Greg's Devblog Par un développeur, pour les développeurs

22août/100

JVM : plusieurs implémentations = plusieurs problèmes

L'open source, c'est génial. Java, c'est fantastique, c'est la liberté, tout le monde peut faire ce qu'il veut avec. Mais si chacun est libre de faire sa JVM, ça veut aussi dire qu'il existe un risque accru de problèmes.

C'était déjà le cas avec le Java sur mobiles, à l'époque des "vieux" Nokia et compagnie : chaque téléphone avait son lot de bugs inclus dans la JVM, et les développeurs devaient faire avec. Du coup, au lieu d'avoir une seule version d'un code qui marche partout (puisque c'était le principe du Java...), il fallait à l'époque être capable de patcher les différentes versions pour les différents téléphones... Pratique !

Cette semaine on a eu ce genre de problèmes, mais en utilisant des trucs standards : la JVM JamVM (qu'on utilise pour sa performance et sa compacité en mémoire) et la version JDBC/JNI de SQLite : avec la JVM de Sun, ça marche parfaitement, tandis qu'avec JamVM, on a un segmentation fault. C'est le genre d'erreur un peu gênant quand on fait du Java, puisque ce n'est pas sensé se produire ^^ Mais c'est l'utilisation de JNI, et donc de code natif, qui introduit ce genre de soucis.

Heureusement (façon de parler), le bug ne se produisait pas sur toutes les requêtes, et on s'est rendu compte qu'il ne se produisait qu'en cas de requête qui aurait du renvoyer un String à null... En mettant les mains dans le code de la couche JNI, en remontant les appels successifs, on a rapidement cerné le soucis :

JNIEXPORT jstring JNICALL Java_org_sqlite_NativeDB_column_1text(JNIEnv *env, jobject this, jlong stmt, jint col)
{
    return (*env)->NewStringUTF(env, (const char*)sqlite3_column_text(toref(stmt), col));
}

Ce petit bout de code fait le pont entre la partie purement C de sqlite (qui renvoie donc un (char *)) et la partie JNI (qui doit renvoyer un String) : on créé un String à partir du (char *) en utilisant les routines fournies par la JVM... Et c'est là que tout s'explique : la JVM de Sun autorise qu'on lui file un pointeur à NULL, et renvoie alors null comme String, alors que JamVM ne l'autorise pas.

On a été assez étonné de tomber sur un problème comme ça (à la fois du côté de JamVM qui ne gère pas ça comme la JVM de Sun, et du côté de sqlitejdbc, qui pourrait jouer la sécurité en faisant la vérification à la main). Le patch a été facile, il suffit de rajouter un petit if...

Moralité ? On ne peut pas toujours faire confiance aux libs et outils qu'on utilise, parfois il faut savoir s'en méfier et mettre le nez dedans :-)

18août/100

JamVM ARM bugs

J'avais parlé dans un précédent billet d'un souci qu'on avait, avec une exception levée dans une méthode toString, pour convertir un long en String... Et bien le problème est de retour, et en fait ça vient de la machine virtuelle qu'on utilise : JamVM.

Le soucis est relativement con, et clairement énoncé dans le bugtracker : "unary minus (-) in jamvm 1.5.4 fails for long on ARM". Or, comment marche la méthode toString ? Si on a un nombre positif, on converti, et si on a un nombre négatif, on affiche '-' au début, on le rend positif, et on le converti. Du coup, la méthode toString va lever une exception et planter lamentablement dès qu'on va convertir un long négatif, puisqu'on n'est pas en mesure de le rendre positif...

Super !

Taggé comme: , , , Aucun commentaire