Empilement d’appels…
Dans le reader qu'on fait, quand je veux ajouter une fonctionnalité (ou juste une méthode à la con) dans la couche du reader, voilà ce qu'il faut ajouter (j'ai mis en rouge les méthodes C/C++, en orange les méthodes Java "génériques", et en vert la partie Android)
- La méthode dans l'objet C++ qui s'occupe de faire le rendu (normal)
- La méthode virtuelle dans la classe abstraite de type Reader
- La méthode JNI qui appelle la méthode sur un objet de type Reader
- La méthode Java dans la classe Reader qui utilise le code JNI
- La méthode Java dans l'interface IReader (pour que tout le monde puisse voir la méthode précédemment ajoutée...)
- La méthode Java dans la classe Presenter (car on n'accède pas directement au Reader)
- La méthode qui utilise la méthode du Presenter dans le code, côté Android (enfin !)
Du coup quand je fais ça je réfléchis bien à si j'ai plusieurs méthodes à ajouter, car... La partie en rouge est sous Eclipse sous Linux (et se compile en ligne de commande), la partie en orange sous Netbeans sous Linux, et la partie en vert sous Eclipse sous MacOSX ^^.
SGBD : tri radix sur GPU
Une équipe de l'Université de Virginia a annoncé avoir atteint le milliard de clés triées par secondes grâce à l'utilisation d'un Radix Sort... sur GPU !
Je n'ai pas encore pris le temps de regarder le code ou les détails techniques, mais en tout cas tout est disponible sur Google Code. Pour information, les meilleures implémentations sur les meilleurs CPU n'atteignent "que" 560 millions de clés triées par secondes. On a donc des performances 2 fois supérieures, ce qui n'est pas mal du tout pour un début...
Pour avoir toutes les infos, le code, et les discussions, c'est par là : http://code.google.com/p/back40computing/wiki/RadixSorting
VM dans VM dans VM…
Je bosse sur un Mac, mais j'ai besoin de compiler des trucs sous Linux, et du coup une partie de notre développement Android, je le fais sous Linux grâce à Parallels. Du coup, quand on fait tourner du code Java sur Android, on a :
- La JVM d'Android qui fait tourner le code
- L'émulateur d'Android qui fait tourner la JVM
- Parallels qui fait tourner Linux pour avoir l'émulateur
Ca fait quand même 3 VM imbriquées, mine de rien... Pas mal ! (en même temps ça rame ^^)
IFA Berlin 2010

Juste un petit mot pour dire que la semaine prochaine j'aurai la chance d'aller à l'IFA 2010, à Berlin, histoire de voir un peu ce qui se fait (et va se faire) niveau smartphones/tablettes/etc
Je ne manquerai pas de faire un rapport dès que j'aurai le temps ! (ça sera l'occasion de tester l'application WordPress pour Android d'ailleurs)
(drôlement sympa ce logo...)
Utiliser le mot-clé « super » en C++
A force de faire du Java, on prend certains réflexes... L'un d'entre eux est d'utiliser le mot-clé "super" pour accéder spécifiquement à une méthode de la super-classe. Du coup quand en codant en C++ j'ai tapé "super" et que j'ai eu droit à une erreur de compilation, ça m'a fait tout drôle...
D'un point de vue pratique, il existe une raison très simple et pour laquelle super ne serait pas disponible en C++ : l'héritage multiple... A quelle classe accèderait-on ainsi ?
En fait, en C++, la façon d'accéder à une méthode d'une superclasse est simple : on utilise explicitement le nom de cette superclasse.
void Foo::haha(void){
Bar::haha();
}
Ca permet effectivement de résoudre le problème posé par l'héritage multiple, et ça a le mérite d'être très clair.
class Derived : public Base
{
private :
typedef Base super; // note that it could be hidden in protected/private section, instead
// Etc.
} ;
En fait c'est tout simple, on ne fait que définir le type super, pour cette classe, comme étant du type de la superclasse. Un premier avantage de cette méthode est que même avec l'héritage multiple, on peut faire fonctionner le mot-clé super en précisant soi-même quelle est la classe à "privilégier". Par contre, on ne peut en choisir qu'une :p
Cette méthode présente cependant un inconvénient majeur, qui peut être source de bug, et qui explique que super soit déclaré comme private (et non public ou protected) : que se passerait-il si on oubliait de le définir dans une sous-classe, et qu'on utilisait quand même le mot-clé super ? Et bien c'est simple, on n'irait pas du tout à la super-classe directe, mais à la super-classe précisée dans le typedef (donc plusieurs niveaux au-dessus, en gros). Dans le genre bug super galère à retrouver, ça peut être violent. Donc autant ne pas prendre le risque et bloquer ce type en le mettant private. Ca signifie qu'on ne pourra pas faire super::super::maMethode(), mais tant pis, il vaut parfois mieux jouer la sécurité.
Je dois dire que quelque part ça m'a fait plaisir de voir cette "bidouille" en C++, car pour moi le C et le C++ sont des langages où avec un peu d'astuce on peut un peu tout faire
(sauf que le GC, il faut le recoder, mais bon...). En tout cas avec de bonnes petites macros et autres, on peut se simplifier la vie, là où dans d'autres langages (comme le Java) on va se reposer à la place sur l'IDE, ses facilités, et éventuellement en branchant par-dessus des systèmes de macros supplémentaires.
Source : Stack Overflow (probablement le meilleur site de questions/réponses pour les développeurs)
JNI : trop d’objets tue l’objet
Un charmant petit plantage sur Android tout à l'heure, alors que le même code marchait très bien sur d'autres JVM (celle de Sun Oracle, ainsi que JamVM). Heureusement, le message d'erreur de Dalvik est très explicite, et m'indique que côté JNI je dépasse le nombre autorisé de local refs (qui est de seulement 512).
En fait dans ce bout de code je génère une table des matières en Java à partir d'une table des matières en C++. Le souci, c'est que celle-ci possède genre 300 entrées, et qu'en Java pour chaque entrée je dois créer 1 objet et 1 String, soit 2 objets au total. 300*2 = 600 > 512... Game Over !
La solution est simple, et les explications sur le pourquoi du comment très clairement exposées sur le site de Sun :
(*env)->DeleteLocalRef(env, jstr);
Une fois que l'objet créé a été refilé comme référence à un autre objet Java, on n'a plus vraiment besoin de garder la référence locale (qui in fine ne sert qu'à s'assurer que le GC ne va pas venir libérer des objets qu'on vient d'allouer côté C...), et donc on peut supprimer la LocalRef.
Blog de Mathias
Petit billet rapide pour dire que Mathias (alias Darkmath pour les intimes) a lancé son blog, avec déjà quelques billets très intéressants sur le parallélisme et la concurrence. Je vous conseille d'y faire un tour !
blog.tamago.fr
Java 7 et ses évolutions

Ce matin j'ai lu un article très intéressant sur Java 7 et les pistes envisagées pour l'évolution du langage. Je ne vais pas tout commenter, mais ça m'a fait plaisir de voir que ça évolue dans le bon sens.
Java est réputé comme étant un langage très (trop) verbeux. Il y a une chose que l'on peut faire "facilement" en C, et de façon moins directe en Java : des pointeurs sur fonction. En Java on se retrouve en fait à utiliser une classe implémentant l'interface "Runnable" (ou autre), et ça devient assez vite moche à lire. Parmi les introductions de Java 7, on pourra donc trouver le type SAM (Single Abstract Method), qui représente en fait une classe n'ayant qu'une méthode abstraite, et les expressions lambda. Je ne vais pas repomper tout l'article car c'est super bien expliqué, mais voici résumé en 1 ligne de code ce que ça pourrait donner de sympa :
Comparator<String> comparator = #(a, b) { a.compareToIgnoreCase(b) };
La syntaxe est quand même super compacte, très lisible, et on se paie même le luxe au passage de ne pas préciser les types, car ceux-ci peuvent être déterminés automagiquement (comme on dit chez nous).
Je ne vais pas détailler le reste des potentiels ajouts/modifications, mais ils permettent tous soit de faire de nouvelles choses (pas forcément révolutionnaires, mais qui rendent le développement plus agréable et évitent d'avoir à faire des hacks foireux), soit de faire la même chose qu'avnat mais de façon plus simple et lisible. En somme, que du bon
Pour ceux que ça intéresse, je vous refile donc le lien : http://blog.developpez.com/adiguba/p9232/java/java7-projet-lambda/
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
Subpixel
Je ne sais plus trop ce que je cherchais quand je suis tombé sur un article sur les subpixels, mais ça m'a rappelé de bons souvenirs et c'est un truc que je trouve assez sympa ^^
Le principe est très simple : un écran (LCD) possède des pixels, mais en fait chaque pixel est lui-même composé de 3 composantes (rouge, vert, bleu), disposées côte à côte. Donc en fait (de façon classique), on a à gauche le sous-pixel rouge, au milieu le sous-pixel vert, et à droite le sous-pixel vert. Grâce à ça, on peut en fait augmenter artificiellement la résolution de l'écran en utilisant ces sous-pixels au lieu de se contenter de pixels pleins. C'est utilisé dans les OS sous différents noms pour le rendu des polices.
En pratique, est-ce super ? Oui et non. Sur certains écrans je trouve que ça donne un côté gênant sur les polices, avec une sensation bizarre de couleur foireuse sur les bords des lettres (puisqu'effectivement le bord sera rouge ou bleu selon les cas). C'est assez subtil, mais ça peut déranger.
C'est assez intéressant comme principe, donc je vous invite à regarder le lien vite fait (ainsi que les images qui vont avec). Sinon, pour l'anecdote, de temps en temps les sous-pixels donnent des effets bizarres : j'avais un affichage avec une zone rouge, et au-dessus une zone bleue. Et bien j'avais l'impression que les 2 zones n'étaient pas alignées horizontalement, alors que c'était le cas. Du moins, au niveau du rendu/soft c'est le cas, mais effectivement en pratique si on fait des zones purement rouges et purement bleues, elles sont par nature (sur les LCD) légèrement décalées.
(à noter que comme toujours l'article wikipedia sur ce sujet est assez sympa aussi)
Déterminer le type d’un fichier dont on n’a pas le nom
Dans le projet sur lequel on bosse, on a une couche en Java qui appelle du code natif en C. Quand on télécharge une image, on récupère au final un buffer que l'on va faire passer à la couche C pour décompression/conversion bien comme il faut pour notre eBook.
Seulement voilà, la fonction générique ne prend qu'un buffer et sa taille comme argument, du coup le hack qui avait été mis en place était de dire que par défaut c'est un PNG, et puis si jamais libpng se chie dessus, on teste autre chose. Bon, un peu crado, et pas super efficace.
En fait il est possible de déterminer si c'est un PNG ou un JPG assez facilement, puisque ceux-ci ont toujours les mêmes entêtes... En regardant les 4 ou 8 premiers octets, on sait donc à quoi on a affaire. Simple, et efficace. Comme j'avais la flemme je me suis basé uniquement sur les 4 premiers, et du coup voilà ce que je recherche :
Pour trouver ce genre d'infos, vous avez plusieurs solutions. La première est bien entendue d'afficher les premiers octets du fichier (ou de l'ouvrir dans un éditeur type bloc-note), mais la seconde est de faire ça proprement et d'aller voir sur http://www.wotsit.org/ pour obtenir de vraies informations officielles sur les formats de fichier, le stockage des données à l'intérieur, etc.
JSON vs XML
Du coup, à certains endroits, j'ai remplacé ça par du XML. C'est assez pratique au cours du développement car si les structures de données évoluent (essentiellement par l'ajout de nouveaux champs, ou le déplacement/réorganisation de la structure), les méthodes pour parser le XML changent très peu (voire pas du tout si on n'a fait qu'ajouter un champs), donc c'est super pratique et évolutif. Sauf que le XML, c'est un poil lourd (à lire et à écrire), avec plein de petits cas foireux et tout.
C'est là qu'intervient JSON : une syntaxe un peu façon XML, mais prévue pour du Javascript à la base, et qui est un peu plus simple tout en offrant (globalement) les mêmes possibilités. Ce n'est pas révolutionnaire en terme de possibilités, mais le fichier final est généralement plus petits, et le parseur est moins complexe, donc pour les besoins de petits développement rapides ça m'a l'air plus adapté.
Petit comparatif rapide entre XML et JSON (je repompe celui de Wikipedia parce qu'il est simple et illustratif ^^)
Syntaxe JSON
{
"firstName": "John",
"lastName": "Smith",
"age": 25,
"address": {
"streetAddress": "21 2nd Street",
"city": "New York",
"state": "NY",
"postalCode": "10021"
},
"phoneNumber": [
{
"type": "home",
"number": "212 555-1234"
},
{
"type": "fax",
"number": "646 555-4567"
}
]
}
Syntaxe XML
<xml>
<Object>
<Property><Key>firstName</Key> <String>John</String></Property>
<Property><Key>lastName</Key> <String>Smith</String></Property>
<Property><Key>age</Key> <Number>25</Number></Property>
<Property><Key>address</Key>
<Object>
<Property><Key>streetAddress</Key> <String>21 2nd Street</String></Property>
<Property><Key>city</Key> <String>New York</String></Property>
<Property><Key>state</Key> <String>NY</String></Property>
<Property><Key>postalCode</Key> <String>10021</String></Property>
</Object>
</Property>
<Property><Key>phoneNumber</Key>
<Array>
<Object>
<Property><Key>type</Key> <String>home</String></Property>
<Property><Key>number</Key> <String>212 555-1234</String></Property>
</Object>
<Object>
<Property><Key>type</Key> <String>fax</String></Property>
<Property><Key>number</Key> <String>646 555-4567</String></Property>
</Object>
</Array>
</Property>
</Object>
</xml>
Bon, c'est un exemple un peu extrême, et en vrai on peut faire mieux pour la syntaxe XML en utilisant judicieusement les attributs. Mais ça illustre le fait que la syntaxe JSON est tout de même plus lisible et épurée, essentiellement grâce à la suppression des balises fermantes. On distingue une particularité de JSON que je trouve pas mal : on a à la fois '{' et '[', qui ont des significations différentes :- { pour les objets- [ pour les listes/arrays/tableaux (c'est pareil)
Il faut tout de même relativiser un peu car la sytaxe XML de l'exemple est particulièrement verbeuse, et qu'en utilisant des attributs on peut obtenir une version XML aussi courte que la version JSON... Mais ce qui m'intéresse dans ce format est plutôt la simplicité pour le parser, donc je vais probablement migrer quelques petits trucs dessus très prochainement.
Source : Wikipedia
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 !
IA Challenge
Voici un petit lien sur lequel j'étais tombé par hasard il y a quelques jours : IA Challenge. Il s'agit d'un concours d'IA en javascript : on programme une IA pour un petit tank, et le jour J les tanks s'affronteront par groupes de 4.
C'est une initiative assez sympa, donc j'invite un maximum de monde à y participer !
Effet Pygmalion

Pendant les vacances, mon cousin m'a parlé de l'Effet Pygmalion, en m'expliquant qu'en gros la réussite d'un élève dans le milieu scolaire dépendait quasi essentiellement de l'attente de ses professeurs.
Je suis allé regarder ça vite fait sur Wikipedia, et globalement, on peut dire que des expériences ont montré que c'était le cas. L'article est super court, donc je vous conseille de le lire
http://fr.wikipedia.org/wiki/Effet_Pygmalion
Je m'interroge surtout sur la façon dont on pourrait imaginer utiliser cet effet dans un milieu professionnel plutôt que scolaire. Parce que bon, en théorie, il suffit de persuader quelqu'un qu'il a un fort potentiel (à tort ou à raison) et lui montrer qu'on attend de grandes choses de lui pour que cela se réalise (plus ou moins, certes).
Dans le même ordre d'idée, dans quelle mesure serions-nous capable d'auto-persuasion pour se booster soi-même ? ^^
(bon, ok, les billets à tendance psy c'est pas trop mon truc)