IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Tutoriel sur la compréhension de la machine virtuelle Java

Image non disponible

Tutoriel sur la comprhension de la machine virtuelle Java

Image non disponible


prcdentsommairesuivant

II-A. Gnralits sur la JVM

Avant de nous intresser au bytecode Java, il est ncessaire de comprendre comment fonctionne dans les grandes lignes la JVM.

Tous les articles dj publis de la srie portent le tag jvmhardcore.

Le JRE est compos de l'API Java et de la JVM. Le rle de la JVM est de lire une application compose de fichiers .class sous diffrentes formes (zip, jar, war, un simple tableau d'octets, etc.) l'aide d'un chargeur de classes et de l'excuter, ainsi que l'API Java.

D'une manire gnrale, une Machine Virtuelle (VM) est une implmentation logicielle d'une architecture physique ou hypothtique. Il existe deux types de machines virtuelles, les VM systme et les VM applicatives. La JVM fait partie de la seconde catgorie. Elle est excute comme n'importe quelle application sur un systme d'exploitation hte et est associe un seul processus. Son but est de fournir un environnement de programmation indpendant de la plate-forme qui fait abstraction du matriel sous-jacent et/ou du systme d'exploitation, et permet un programme de s'excuter de la mme manire sur n'importe quelle plate-forme. La JVM utilise un bytecode, un langage intermdiaire entre Java (le langage utilisateur) et le langage machine (Virtual machine en anglais).

Bien que dans JVM, le J signifie Java, il est thoriquement possible d'implmenter un compilateur compilant n'importe quel langage en bytecode pour la JVM. Mais en pratique certains langages sont trs difficiles implmenter de manire efficiente.

Quelques particularits de la JVM

  • Machine virtuelle base sur le modle de la pile: les architectures d'ordinateurs les plus populaires telles que l'architecture Intel x86 et l'architecture ARM sont bases sur des registres. Cependant la JVM est base sur le modle de la pile (LIFO, stack-based). Dalvik, la machine virtuelle d'Android ne suit pas la JVMS, puisqu'elle est base sur des registres.
  • Rfrences symboliques: tous les types (classes et interfaces), l'exception des primitifs (boolean, int, float, etc.), sont dsigns par une rfrence symbolique et non une rfrence explicite d'une adresse mmoire.
  • Ramasse-miettes: l'instance d'une classe est cre explicitement par le code du dveloppeur et est dtruite automatiquement par le ramasse-miettes.
  • Garantie de l'indpendance de la plate-forme en dfinissant clairement les types primitifs: la taille des types primitifs est fixe par la JVMS.
  • Ordre des octets du rseau: toujours dans un souci de maintenir l'indpendance de la plate-forme, la reprsentation des donnes doit tre fixe. L'ordre des octets du rseau a t choisi. Il s'agit en ralit de l'orientation big-endian (l'octet de poids le plus fort se trouve gauche et est stock en premier en mmoire).

II-B. Zones de donnes d'excution (Runtime Data Areas)

Le code Java est excut en suivant le processus ci-dessous:

Image non disponible

Pour l'instant, seule l'tude des zones de donnes d'excution nous sera utile pour comprendre le format d'un fichier .class.

Image non disponible

La JVM dfinit diffrentes zones de donnes d'excution qui sont utilises durant l'excution d'un programme. Certaines de ces zones de donnes sont cres lorsque la JVM est lance et sont dtruites lorsqu'elle s'arrte. Les autres zones sont propres chaque fil d'excution (thread). Les zones de donnes par fils d'excution sont cres lorsque le fil d'excution est cr et sont dtruites lorsqu'il se termine.

II-B-1. Le tas (HEAP)

La JVM a un tas partag par tous les fils d'excution. Le tas est une zone de donnes d'excution dans laquelle toutes les instances de classes et les tableaux sont stocks. Le tas est cr au dmarrage de la JVM. Les objets n'tant pas explicitement dsallous de la mmoire, lorsqu'ils ne sont plus rfrencs le ramasse-miettes les supprime du tas.

II-B-2. Zone de mthodes (METHOD AREA)

Lorsque le chargeur de classes charge une classe, il stocke sa structure (le pool de constantes, les donnes des champs et des mthodes, et le code des mthodes et des constructeurs) dans la Zone de Mthodes. Il s'agit d'un espace mmoire partag par tous les fils d'excution et la JVMS n'impose pas qu'il soit libr par le ramasse-miettes et donc qu'il fasse partie du tas (heap).

II-B-3. Pool de constantes d'excution (RUNTIME CONSTANT POOL)

Le pool de constantes est une reprsentation d'excution par classe ou par interface du pool de constantes dfini dans un fichier .class, sur lequel nous reviendrons dans quelques semaines.

Il contient plusieurs sortes de constantes, des littrales numriques connues lors de la compilation aux rfrences de champs ou de mthodes devant tre rsolues lors de l'excution. Le pool de constantes d'excution est comparable une table de symboles utilise par un langage de programmation conventionnel, bien qu'il contienne plus de types de donnes qu'une table de symboles standard.

Chaque pool de constantes d'excution est allou partir de la zone de mthodes. Le pool de constantes d'excution pour une classe ou une interface est construit lorsque la classe ou l'interface est cre par la JVM.

II-C. Fils d'excution (THREADS)

Il existe deux types de fils d'excution Java:

  • les fils d'excution de type dmon;
  • et les fils d'excution de type non-dmon.

Les fils d'excution de type dmon s'arrtent lorsqu'il n'y a plus de fils d'excution de type non-dmon. Mme si une application ne cre pas de fils d'excution, la JVM en cre plusieurs, dont la plupart sont des fils d'excution de type dmon.

Le fil d'excution principal d'une application est celui excutant la mthode main(). Il est le premier et le dernier fil d'excution de type non-dmon s'excuter. Lorsque l'on atteint la fin de la mthode main() -et de tous les fils d'excution de type non-dmon lancs lors de son excution- le fil d'excution se termine, mettant fin aux fils d'excution de type dmon et par consquent l'excution de la JVM.

noter qu'un fil d'excution de type dmon peut tre cr au sein d'une application.

II-D. Pointeur d'instruction (PROGRAM COUNTER)

La JVM peut supporter l'excution de plusieurs fils d'excution en parallle. Chaque fil d'excution a son propre pointeur d'instruction (PC Program Counter). tout moment, chaque fil d'excution excute le code d'une seule mthode, la mthode courante pour ce fil d'excution. Si cette mthode n'est pas native, le pointeur d'instructions contient l'adresse de l'instruction de la JVM en cours d'excution. Si la mthode en cours d'excution par le fil d'excution est native, le pointeur d'instructions est indfini.

II-E. Piles Java (JAVA VIRTUAL MACHINE STACKS)

Chaque fil d'excution de la JVM a une pile qui lui est propre, cre en mme temps que le fil d'excution. Une pile stocke des cadres (identifis par C0, C1, etc. dans l'illustration ci-dessous).

Image non disponible

II-F. Piles de mthodes natives (NATIVE METHOD STACKS)

l'instar des mthodes Java qui sont excutes dans les piles Java, les mthodes natives (gnralement en C/C++) sont excutes dans les piles de mthodes natives. Les piles de mthodes natives sont gnralement alloues par fil d'excution lorsqu'il est cr.

II-G. Cadres (FRAMES)

Un cadre est utilis pour stocker des donnes et des rsultats partiels, ainsi que pour effectuer des liaisons dynamiquement, retourner des valeurs de mthodes et transmettre des exceptions.

Image non disponible

Un nouveau cadre est cr chaque fois qu'une mthode est appele. Un cadre est dtruit lorsque l'excution de la mthode est termine, que ce soit normalement ou non (si une exception est leve). Les cadres sont allous dans la pile Java du fil d'excution crant le cadre. Chaque cadre a son propre tableau de variables locales, sa pile d'oprandes et une rfrence vers le pool de constantes d'excution de la classe de la mthode courante.

Seulement un cadre est actif la fois par fil d'excution, le cadre de la mthode en cours d'excution. Ce cadre est appel le cadre courant, et sa mthode, la mthode courante. La classe dans laquelle la mthode courante est dfinie est la classe courante.

Un cadre n'est plus courant si sa mthode appelle une autre mthode ou si sa mthode se termine. Quand une mthode est appele, un nouveau cadre est cr et devient le cadre courant lorsque le contrle est transfr la nouvelle mthode. Au retour de la mthode, le cadre courant retransmet le rsultat de sa mthode au cadre prcdent '-s'il existe-. Le cadre courant est alors supprim et le cadre prcdent redevient le cadre courant.

II-G-1. Variables locales

Chaque cadre contient un tableau de variables nomm variables locales. La taille du tableau est dtermine lors de la compilation (nous y reviendrons dans une partie ultrieure).

Les variables locales sont adresses par index comme n'importe quel tableau d'un langage de programmation standard. L'index de la premire variable locale est zro et celui de la dernire est gal la taille du tableau moins un.

La JVM utilise les variables locales pour passer des paramtres la mthode appele. Lorsqu'une mthode de classe (statique) est appele, tous les paramtres sont stocks dans les variables locales de manire conscutive partir de l'index zro. Lorsqu'une mthode d'instance est appele, la variable l'index zro est toujours une rfrence de l'objet (this) sur laquelle la mthode a t appele. Les paramtres sont quant eux stocks de manire conscutive partir de l'index un.

Les variables locales sont aussi utilises pour stocker des rsultats partiels.

II-G-2. Pile d'oprandes

Chaque cadre contient une pile Last In First Out (LIFO) nomme pile d'oprandes. La taille maximum de la pile est dtermine lors de la compilation (nous y reviendrons aussi dans une partie ultrieure). La pile d'oprandes est vide lorsque le cadre la contenant est cr.

Chaque entre de la pile peut contenir une valeur de n'importe quel type connu de la JVM.

II-G-3. Liaison dynamique

Chaque cadre contient une rfrence pointant vers le pool de constantes d'excution pour que le type de la mthode courante supporte la liaison dynamique du code de la mthode. En d'autres termes lorsqu'une mthode d'une classe A fait rfrence une classe B, dans un fichier .class le lien entre A et B est symbolique. La liaison dynamique traduit cette rfrence symbolique en une rfrence concrte, chargeant si ncessaire la classe B et traduisant les diffrents accs cette classe (champs, mthodes d'instance, etc.) par des offsets permettant de localiser leur position en mmoire.

Image non disponible

Notes:

Dans le cadre correspondant la mthode main(), la variable l'index 0 (ra) correspond une rfrence au tableau pass en paramtre (nomm a ici).

vl0 et vl1 correspondent aux variables locales d'index 0 et 1.

Si certains points vous semblent encore obscurs, normalement tout devrait devenir plus clair dans les prochaines parties. Nous aborderons notamment le cas de la surcharge/redfinition d'une mthode.

II-H. What's next?

Dans la prochaine partie, nous nous intresserons un outil nomm Plume que nous utiliserons au cours des prochains articles. Plume est un assembleur/dsassembleur de bytecode, qui -comme Jasmin-permet d'crire un fichier au format texte en utilisant une syntaxe proche de celle dcrite dans la spcification de la machine virtuelle Java pour le transformer en un fichier .class. Plume peut aussi tre utilis comme ASM pour crer du bytecode la vole en Java, le charger l'aide d'un chargeur de classes et l'excuter.

Plume ayant un objectif ducatif, pour son implmentation -que nous tudierons- la simplicit du code a t privilgie face aux performances.


prcdentsommairesuivant

Copyright © 2016 SOAT. Aucune reproduction, même partielle, ne peut être faite de ce site ni de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.