2010-01-30 5 views
7

Je suis novice en Java et j'apprends toujours. J'ai eu la tête dans les classes internes et anonymes. Maintenant, j'ai une question technique sur comment java ressemble en mémoire, quand allouer des objets, définir des classes, etc.A quoi ressemble Java en mémoire

Comme à quoi ressemble la mémoire quand j'ai un champ qui est un objet qui est défini dans une classe extérieure vs une classe interne. Les classes statiques sont-elles différentes de celles qui ne sont pas statiques?

J'ai juste besoin d'une référence visuelle.

Merci les gars

+0

Le "comment" est un détail de mise en œuvre, non spec définie. Cela dit, ce livre ne vous dit pas comment une implémentation Java le fait réellement, mais il vous dit comment une machine virtuelle de type Java peut le faire: http://www1.idc.ac.il/tecs/ – Dinah

Répondre

3

Les détails sont dans la mise en œuvre (pas la spécification). Cependant, les implémentations suivent généralement un modèle très simple. La plupart de la disposition de la mémoire en Java est très simple et directe. Ma terminologie ne correspond peut-être pas à la terminologie Java, car je ne fais pas beaucoup de programmation Java.

En général, un objet commence par un pointeur sur son vtable, puis possède un tas de champs qui suivent. Les champs sont des types primitifs (int/bool/float) ou des pointeurs vers des objets. C'est tout pour les objets. (Les classes sont aussi des objets.) Les pointeurs Null sont comme C, ils sont invalides, pas comme Python, où None est un objet.

Dans une classe interne, il existe un champ caché supplémentaire qui pointe vers une instance de la classe externe. C'est ainsi que les classes internes accèdent aux données de la classe externe. Les cours anonymes fonctionnent de la même manière. Les méthodes statiques sont juste des méthodes sur la classe au lieu de méthodes sur l'instance.

Le vtable est où toute la magie se produit. Chaque classe a son propre vtable partagé entre tous les objets. Le vtable a des informations sur la classe telles que la taille de ses instances et comment les champs sont disposés. Cette information est utilisée par le garbage collector. Le vtable a également un pointeur vers toutes les méthodes que la classe implémente. Lorsque vous appelez une méthode, l'exécution extrait d'abord le pointeur vtable de l'objet, puis extrait le pointeur de méthode de la table vtable, puis appelle la méthode et passe l'objet à la méthode en tant que paramètre implicite. C'est similaire à C++, mais beaucoup plus simple à implémenter. Le processus peut être ignoré si la méthode ou la classe est "finale". Je sais que Java n'a pas vraiment de "pointeurs", il a des "poignées symboliques" ou quelque chose comme ça, mais les implémentations courantes utilisent simplement des anciens pointeurs.

1

Comme quoi ressemble la mémoire comme quand je ai un champ qui est un objet qui est défini dans une classe à l'extérieur contre une classe interne. Est-ce que les classes statiques semblent différente de non statique?

Une instance de classe interne non statique (ou anonyme) aura une référence à l'instance de la classe externe qui a été utilisé pour instancier. C'est ce qui permet à une méthode de la classe interne de référencer les membres de niveau instance déclarés dans la classe englobante. Normalement, cette référence est passée à la classe interne en tant que paramètre supplémentaire caché dans le constructeur. Mais si vous utilisez la réflexion pour créer une instance de classe interne, vous devez fournir explicitement ce paramètre supplémentaire.

(Notez qu'un mécanisme différent est utilisé lorsqu'une classe anonyme utilise les sections locales/paramètres dans le cadre de la méthode qui instancie ...)

Si vous avez besoin de plus de détails, vous pouvez utiliser javap à désassembler les bytecodes de certaines classes d'exemples simples.

J'ai juste besoin d'une référence visuelle.

Désolé, je ne fais pas de jolies images :-)

+0

ok je trouve bonne ressource avec des diagrammes :) http://www.artima.com/insidejvm/ed2/jvm.html –

+0

+1 pour ne pas faire de jolies photos – stacker

+0

@pp - J'ai regardé à travers cette ressource, et je ne pouvais pas voir tout des images qui ont répondu à cette question particulière sur les classes internes. Vous devrez peut-être acheter une copie papier du livre ... –

3

Bienvenue dans le monde de Java. Contrairement au langage C, où la construction de la langue et la représentation de la mémoire sont très proches les unes des autres, Java est un peu plus compliqué. Tout d'abord, quand on parle de Java, cela peut signifier deux choses: Java-the-language et Java-the-platform. Ici, je veux dire Java pour être le langage de programmation Java. Le code écrit en Java est d'abord compilé en bytecode, code machine pour Java Virtual Machine. Si vous êtes intéressé par les détails de la langue Java, voici The Java Language Specification. Et pour la JVM, il y a The Java Virtual Machine Specification. À quoi ressemble la mémoire quand j'ai un champ qui est un objet défini dans une classe externe par rapport à une classe interne. Je vais interpréter cela comme étant la disposition de la mémoire dans Java Virtual Machine, puisque la mise en page physique est à la mise en œuvre de la JVM. Pour cela, j'ai écrémé Structure of the Java Virtual Machine.

Comme le langage Java, la machine virtuelle Java fonctionne sur deux types de types: types primitifs et types de référence. Il y a, en conséquence, deux sortes de valeurs qui peuvent être stockées dans des variables, passées en arguments, renvoyées par des méthodes, et exploitées: les valeurs primitives et les valeurs de référence.

La machine virtuelle Java s'attend à ce que presque toutes les vérifications de types soient effectuées au moment de la compilation, et non par la machine virtuelle Java elle-même. En particulier, les données n'ont pas besoin d'être marquées ou autrement inspectables pour déterminer les types.

....

est considéré comme une référence à un objet d'avoir Java Virtual Machine type reference. Les valeurs de type reference peuvent être considérées comme des pointeurs vers des objets.

Donc la réponse semble être que les deux champs sembleraient exactement les mêmes: reference.

0

statique fonctionne classe (imbriquée) exactement de la même manière qu'une classe de niveau supérieur. La seule différence est que son nom a un autre nom de classe le préfixant. (Si vous regardez les fichiers .class compilés, vous verrez que vous obtiendrez quelque chose comme "Outer $ Nested.class" pour une classe nommée imbriquée imbriquée dans une classe nommée Outer.)

un champ caché qui est une référence à l'instance contenant de sa classe externe.Lorsque vous écrivez:

class Outer { 
    final int x; 

    class Nested { 
    int y; 

    Nested(int y) { 
     this.y = y; 
    } 

    int bar() { 
     return x + y; 
    } 
    } 

    void foo() { 
    Nested n = new Nested(5); 
    } 
} 

Il est comme si vous aviez écrit:

class Outer { 
    final int x; 

    static class Nested { 
    Outer outer; 
    int y; 

    Nested(Outer outer, int y) { 
     this.outer = outer; 
     this.y = y; 
    } 

    int bar() { 
     return outer.x + y; 
    } 
    } 

    void foo() { 
    Nested n = new Nested(this, 5); 
    } 
} 

Le nom de ce champ caché (que je l'ai appelé « extérieur » ici) est caché à vous, si vous pouvez vous y référer en disant Outer.this à l'intérieur de la classe interne (où Outer est le nom de votre classe-dehors, bien sûr). De même, notez que lorsqu'une méthode dans la classe interne fait référence à quelque chose dans la classe externe, cette référence est en réalité via cette référence cachée à la classe externe.

Il y a quelques complications supplémentaires concernant le fonctionnement du contrôle d'accès (par exemple: private) avec les classes imbriquées/internes, mais cela n'affecte pas vraiment la question de "mémoire" que vous posez.

0
public class I { 
    class inner { 
     public void ctor() {}; 
    } 
} 

On dirait dissasemmbled comme, vous pouvez utiliser JAD

class I$inner { 

    // Field descriptor #6 LI; 
    final synthetic I this$0; 

    // Method descriptor #8 (LI;)V 
    // Stack: 2, Locals: 2 
    I$inner(I arg0); 
    0 aload_0 [this] 
    1 aload_1 
    2 putfield I$inner.this$0 : I [10] 
    5 aload_0 [this] 
    6 invokespecial java.lang.Object() [12] 
    9 return 
     Line numbers: 
     [pc: 0, line: 3] 
     Local variable table: 
     [pc: 0, pc: 10] local: this index: 0 type: I.inner 

    // Method descriptor #14()V 
    // Stack: 0, Locals: 1 
    public void ctor(); 
    0 return 
     Line numbers: 
     [pc: 0, line: 4] 
     Local variable table: 
     [pc: 0, pc: 1] local: this index: 0 type: I.inner 
} 

En tant que hexdump il commencerait par 0xcafebabe

Questions connexes