Aller au contenu

Atelier 12

Dans cette dernière séance de laboratoire, vous pratiquerez le profilage, la décompilation et l'obfuscation. Pour les exercices de cette dernière séance de laboratoire, vous travaillerez avec le projet PrimeChecker, disponible sur GitLab.

Profilage

  • Le profilage est un moyen fiable de déterminer quelle partie de votre code consomme réellement des ressources.
  • Dans le cadre de ce cours, nous nous intéressons principalement aux techniques basées sur l'échantillonnage pour mesurer quelles méthodes consomment le plus de cycles CPU.

Graphiques en flamme avec IntelliJ

  • Les graphiques en flamme sont une représentation visuelle du temps CPU, basée sur des piles d'appels échantillonnées périodiquement.
  • Pour une meilleure lisibilité, les piles sont triées et colorées, ce qui donne une structure ressemblant à une flamme.
  • IntelliJ dispose d'un profileur intégré qui génère automatiquement des graphiques en flamme à partir des échantillons de piles d'appels collectés.

À vous de jouer

  • Avant de pouvoir effectuer un profilage, nous avons besoin d'un programme qui s'exécute un peu plus longtemps que quelques appels de méthode.
  • Reprenez les tests du projet PrimeChecker utilisé précédemment et ajoutez un nouveau test qui compte combien de nombres premiers existent en dessous de 10000. Il devrait en trouver 1229 :
    @Test
    public void testPrimesBelow10000() {
      Assert.assertEquals(1229, PrimeChecker.countPrimeNumbersBelow(10000));
    }
    
  • Au lieu d'exécuter le code avec Maven, utilisez le triangle vert à gauche du test. Ne cliquez pas simplement, mais faites un clic droit, puis sélectionnez Profile with IntelliJ profiler...
  • Le test s'exécutera comme d'habitude, mais IntelliJ affichera une fenêtre contextuelle : "Profiler data is ready" avec une option "Open".
    • Avant de continuer, notez le temps d'exécution du test, c'est-à-dire combien de millisecondes ont été nécessaires pour l'exécuter.
  • Cliquez sur "Open". Un graphique en flamme apparaîtra. Inspectez ce graphique et identifiez quelle de vos méthodes ( boîtes en orange) consomme le plus de ressources.
  • Revenez à votre code de production. Plusieurs lignes présentent maintenant un symbole de flamme sur le côté.
    • Identifiez quelles lignes sont considérées comme les plus coûteuses. Vous devriez trouver une seule ligne responsable de la grande majorité de la consommation CPU.
    • Si possible, essayez d’optimiser votre code, en améliorant ou en supprimant les lignes qui prennent trop de temps.
  • Exécutez à nouveau votre code : Comparez la durée du test avec celle mesurée auparavant. Vérifiez s’il y a une accélération significative.

Décompilation de code

En classe, vous avez vu un exemple d'utilisation de l'outil CFR (Class File Reader).

Class File Reader

  • Le CFR peut être utilisé sur n'importe quel bytecode Java. Le moyen le plus simple d'obtenir un bytecode à utiliser est de décompiler votre propre code.
  • Le CFR est disponible gratuitement sur le site du développeur

À vous de jouer

Essayez de décompiler une de vos propres classes Halma !

  1. Utilisez mvn clean package pour produire un fichier jar.
  2. Extrayez le contenu de votre fichier jar et trouvez le fichier class d’une classe non triviale, par exemple votre implémentation de Controller.
  3. Utilisez CFR pour décompiler le fichier class et reconstruire le fichier source .java.
  4. Comparez côte à côte votre code source original avec celui produit par le décompilateur.

Utilisez un outil de comparaison visuelle

icdiff est un outil de ligne de commande pratique pour repérer rapidement les différences entre deux fichiers.

(Bonus : Si vous aimez la récursivité, essayez de décompiler le décompilateur avec le décompilateur !)

Obfuscation de code

Les obfuscateurs sont des outils permettant de réduire le risque de décompilation pour éviter l’inspection de code non autorisée.

ProGuard

  • ProGuard est un outil gratuit qui permet de remplacer (entre autres) tous les noms de variables par des identifiants similaires phonétiquement ou visuellement.
  • Ainsi, une fois le logiciel obfusqué, il devient très difficile à interpréter ou à rétroconcevoir pour un humain.
  • ProGuard est disponible gratuitement sur le GitHub du projet.

À vous de jouer

  1. Obfusquez votre propre fichier jar Halma avec ProGuard. Quelques éléments à garder en tête :
    • Vous avez besoin d’un fichier de configuration (voir le matériel de cours pour un exemple). Assurez-vous d’indiquer la bonne classe de lancement (si la méthode main est obfusquée, votre code ne pourra plus s’exécuter).
    • ProGuard agit directement sur un fichier jar. Assurez-vous que votre fichier jar Halma initial est fonctionnel.
  2. Essayez de décompiler votre jar.
    • Extrayez le jar et trouvez les fichiers de classe.
    • Décompilez certains fichiers de classe avec CFR.
    • Comparez le code obfusqué avec le code source original.
  3. Vérifiez votre fichier jar obfusqué : il doit toujours être fonctionnel.
  4. (Bonus : Ajoutez ProGuard à votre configuration gitlab.ci, afin que le fichier jar généré par le job pages de GitLab soit toujours protégé contre la décompilation.)