Maison  >  Article  >  Java  >  Analyse du principe HelloWorld en Java

Analyse du principe HelloWorld en Java

黄舟
黄舟original
2017-05-21 10:28:022098parcourir

Le premier programme que nous utilisons pour apprendre Java est "hello world". Ce qui suit est une analyse des principes de Java HelloWorld à travers un exemple de code. Les amis intéressés peuvent apprendre ensemble

Le premier programme pour nous permettre d'apprendre Java est "hello world"

 public class HelloWorld {
   public static void main(String[] args) {
     System.out.println("hello world");
   }
}

À quoi ressemble le programme ci-dessus ? Comment afficher « hello world » à l'écran ? C'est ce qui devait initialement être expliqué, c'est-à-dire le principe de System.out.println("hello world").

Jetons d'abord un coup d'œil au processus de System.out.println. Examinons d'abord la définition de out dans System.java. Le code source est le suivant :

public final class System {
   ... 
   public final static PrintStream out = null; 
   ...
 }

À partir de là, nous constatons que

(01) out est statique Variable.

(02) Et out est un objet PrintStream

Il existe de nombreuses méthodes surchargées println() dans PrintStream.java.

OK, nous savons que out est un objet PrintStream. Ensuite, voyez comment il est initialisé et comment il est lié à la sortie à l'écran ?

Analysons-le étape par étape. Tout d'abord, examinons la méthode initializeSystemClass() de System.java.

1. Le code source de initializeSystemClass() est le suivant : Marquez la partie out en rouge

 private static void initializeSystemClass() {
   props = new Properties();
   initProperties(props); // initialized by the VM
   sun.misc.VM.saveAndRemoveProperties(props);
   lineSeparator = props.getProperty("line.separator");
   sun.misc.Version.init();
   FileInputStream fdIn = new FileInputStream(FileDescriptor.in);
   FileOutputStream fdOut = new FileOutputStream(FileDescriptor.out);
   FileOutputStream fdErr = new FileOutputStream(FileDescriptor.err);
   setIn(new BufferedInputStream(fdIn));
   setOut0(new PrintStream(new BufferedOutputStream(fdOut, 128), true));
   setErr0(new PrintStream(new BufferedOutputStream(fdErr, 128), true));
   loadLibrary("zip");
   Terminator.setup();
   sun.misc.VM.initializeOSEnvironment();
   Thread current = Thread.currentThread();
   current.getThreadGroup().add(current);
   setJavaLangAccess();
   sun.misc.VM.booted();
 }
Il suffit de prêter attention à la partie du code rouge ci-dessus : c'est-à-dire,

FileOutputStream fdOut = new FileOutputStream(FileDescriptor.out);
setOut0(new PrintStream(new BufferedOutputStream(fdOut, 128), true));
Ces deux phrases peuvent être décomposées selon les étapes suivantes :

Étape 1 FileDescriptor fd = FileDescriptor.out;

Étape 2 FileOutputStream fdOut = new FileOutputStream( fd);

Étape 3 BufferedOutputStream bufOut = new BufferedOutputStream(fdOut, 128);

Étape 4 PrintStream ps = new PrintStream(bufout, true);

Étape 5 setOut0 ( ps);

Explication :

(01) Étape 1, extraire le membre statique dans FileDescriptor.java est un objet FileDescriptor, qui est en fait une "sortie standard (écran)". identifiant.


Le code lié à FileDescriptor.out dans FileDescriptor.java est le suivant :

 public final class FileDescriptor {
    private int fd;
   public static final FileDescriptor out = new FileDescriptor(1);
   private FileDescriptor(int fd) {
     this.fd = fd;
     useCount = new AtomicInteger();
   }
   ...
 }
(02) Créer un "File Output Stream" correspondant à "Standard Output (Screen )".

(03) Créer un "flux de sortie tamponné" correspondant au "flux de sortie du fichier". Le but est d'ajouter une fonctionnalité de « mise en mémoire tampon » au « File Output Stream ».

(04) Créer un "flux de sortie d'impression" correspondant au "flux de sortie tamponné". Le but est de fournir une

interface d'impression pratique pour le "flux de sortie tamponné", telle que print(), println(), printf(); et rapidement.

(05) Exécutez setOut0(ps);

Ensuite, analysez setOut0(ps) à l'étape 5. Vérifiez la déclaration de setOut0() dans System.java, comme suit :

private static native void setOut0(PrintStream out);
À partir de là, nous constatons que setOut0() est une méthode native. Grâce à openjdk, nous pouvons trouver son code source correspondant, comme suit :

 JNIEXPORT void JNICALL
 Java_java_lang_System_setOut(JNIEnv *env, jclass cla, jobject stream)
 {
   jfieldID fid =
     (*env)->GetStaticFieldID(env,cla,"out","Ljava/io/PrintStream;");
   if (fid == 0)
     return;
   (*env)->SetStaticObjectField(env,cla,fid,stream);
 }
Explication :

Il s'agit d'une fonction JNI

, faisons-en une simple analyse .

(01) Nom de la fonction

JNIEXPORT void JNICALL Java_java_lang_System_setOut0(JNIEnv *env, jclass cla, jobject stream)
Il s'agit de la méthode d'enregistrement statique de JNI Java_java_lang_System_setOut0(JNIEnv *env, jclass cla, jobject stream) sera la même que setOut0(PrintStream). dans System.java out); de plus, le paramètre stream correspond au paramètre out. Pour faire simple, lorsque nous appelons setOut0(), nous appelons en fait Java_java_lang_System_setOut0().

(02) jfieldID fid = (*env)->GetStaticFieldID(env,cla,"out","Ljava/io/PrintStream;");

Que fait cette phrase consiste à obtenir le jfieldID du membre statique à partir de System.java. "Ljava/io/PrintStream;" signifie que out est un objet java.io.PrintStream.

Le but de récupérer le jfieldID de out est que nous devons changer la valeur de out en exécutant "out's jfieldID".

(03) (*env)->SetStaticObjectField(env,cla,fid,stream);

La fonction de cette phrase est de définir le fid correspondant (fid est le jfieldID de out) La valeur du membre statique est stream.

stream est le paramètre que nous passons à Java_java_lang_System_setOut0(), qui est le paramètre passé à setOut0.

Résumé de ce qui précède. Nous savons que la fonction de setOut0(PrintStream ps) est de définir ps sur la variable statique out de System.java.


Comme mentionné précédemment, FileDescriptor.out est l'identifiant de fichier de la "sortie standard (écran)" de la machine. Nous pouvons généralement comprendre l'identifiant de fichier comme une « sortie standard » représentée par FileDescriptor.out.

Par conséquent, dans initializeSystemClass(), les 5 étapes ci-dessus consistent à encapsuler "FileDescriptor.out". Le System.in encapsulé possède à la fois une fonction de mise en mémoire tampon et des interfaces de fonctionnement pratiques, telles que print(), println() et printf().


Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn