[LINUX] Java-Kompilierung und Ausführung von CLI verstanden

Ich denke, die meiste Zeit benutze ich IDE für die Java-Programmierung. Selbst wenn Sie mit dem Erlernen der Java-Programmierung beginnen, ist dies häufig bei der Vorbereitung der IDE erforderlich. Wenn Anfänger jedoch anfangen, aus der Java-Programmierung in der IDE zu lernen, können sie die von der IDE unterstützten Teile nicht genau verstehen oder nur abhängig von der IDE arbeiten, selbst wenn sie Code in die IDE schreiben können. Ich kann nicht aus dem Staat wachsen. Dieser Artikel richtet sich an Anfänger, um ihr Verständnis zu vertiefen, indem sie einfache Java-Programme mit CLI ohne Verwendung von IDE ausführen. Das detaillierte Lesen oder Schreiben des Programms wird nicht erwähnt. Für Anfänger mögen schwierige Wörter und Konzepte auf dem Weg erscheinen, aber es ist nicht notwendig, sie sofort zu verstehen. Bitte lesen Sie sie durch und verstehen Sie sie nach und nach.

Umgebung

Es wird das Betriebssystem sein, an dem Sie gerade arbeiten, und die Version von Java, die Sie verwenden werden. In diesem Artikel arbeite ich an CentOS, aber wenn Sie vagrant nicht installieren können, können Sie auf Mac arbeiten. Wenn Sie den UNIX-Befehl ersetzen, können Sie an der Windows-Eingabeaufforderung arbeiten (nicht überprüft). ..

OS

Verwenden Sie diese BOX, um eine VM mit Vagrant auf VirtualBox zu starten und darin zu arbeiten.

$ cat /etc/os-release
NAME="CentOS Linux"
VERSION="7 (Core)"
ID="centos"
ID_LIKE="rhel fedora"
VERSION_ID="7"
PRETTY_NAME="CentOS Linux 7 (Core)"
ANSI_COLOR="0;31"
CPE_NAME="cpe:/o:centos:centos:7"
HOME_URL="https://www.centos.org/"
BUG_REPORT_URL="https://bugs.centos.org/"

CENTOS_MANTISBT_PROJECT="CentOS-7"
CENTOS_MANTISBT_PROJECT_VERSION="7"
REDHAT_SUPPORT_PRODUCT="centos"
REDHAT_SUPPORT_PRODUCT_VERSION="7"

Java

Installieren Sie This OpenJDK mit yum und verwenden Sie es.

$ java -version
java 10.0.2 2018-07-17
Java(TM) SE Runtime Environment 18.3 (build 10.0.2+13)
Java HotSpot(TM) 64-Bit Server VM 18.3 (build 10.0.2+13, mixed mode)

$ javac -version
javac 10.0.2

Java-Programm

Java-Programme werden normalerweise vor der Ausführung mit einem Javac-Tool von ".java" bis ".class" Bytecode (auch Zwischencode genannt) kompiliert. Wenn das Programm ausgeführt wird, wird der Bytecode in der JVM auf eine Interpreter-Weise ausgeführt, oder der JIT-Compiler kompiliert ihn erneut in Maschinencode und führt ihn aus. Der JIT-Compiler ist eine der Komponenten von JRE (Java Runtime Environment) und ein Mechanismus zur Optimierung des Maschinencodes von Programmmethoden und zur Verbesserung der Leistung.

Von hier aus kompilieren und führen Sie Java-Programme aus und erstellen Archive mit der CLI.

Grundlegende Kompilierung und Ausführung

Schreiben Sie zunächst ein Programm, das "Hallo Welt" ausgibt, und führen Sie es aus. Die auszuführende Programmdatei lautet wie folgt. Bereiten Sie sie daher mit vi usw. vor.

App.java


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

Kompilieren Sie dies mit Javac.

$ ls
App.java

$ javac App.java

$ ls
App.class  App.java

Sie können sehen, dass die .class-Datei generiert wurde. Führen Sie es dann in Java aus. Beachten Sie, dass das Argument der Klassenname und nicht der Dateiname ist.


$ java App 
Hello world.

Es war einfach, aber ich habe das Programm kompiliert und ausgeführt. Bisher gibt es kein Problem.

Ausführung mit Argumenten

Versuchen Sie, Argumente auszuführen, wenn Sie das Programm ausführen. Nehmen Sie die folgenden Änderungen an der vorherigen Programmdatei vor.

App.java


class App {
    public static void main(String[] args) {
        for (String arg: args) {
            System.out.println(String.format("Hello %s.", arg));
        }
    }
}

Kompilieren und ausführen. Lassen Sie uns im Gegensatz zu früher zur Laufzeit ein Argument übergeben.

$ java App Alice Bob Carol
Hello Alice.
Hello Bob.
Hello Carol.

Sie können sehen, dass das Argument empfangen wurde.

Verwendung anderer Klassen

Versuchen Sie, auf andere Klassen in Ihrem Programm zuzugreifen. Erstellen Sie zunächst eine Human-Klasse, die Menschen als eine andere Klasse in einer anderen Datei darstellt.

Human.java


class Human {
    String name;
    Human(String name) {
            this.name = name;
    }
    void introduceMyself() {
            System.out.println(String.format("My name is %s.", this.name));
    }
}

Instanziieren Sie die Human-Klasse in der Hauptmethode der App-Klasse.

App.java


class App {
    public static void main(String[] args) {
        for (String arg: args) {
            Human human = new Human(arg);
            human.introduceMyself();
        }
    }
}

Lassen Sie es uns kompilieren.

$ ls
App.java  Human.java

$ javac App.java

$ ls
App.class  App.java  Human.class  Human.java

Sie können sehen, dass Human zusammen mit der Kompilierung der App kompiliert wurde.

$ java App Alice Bob Carol
My name is Alice.
My name is Bob.
My name is Carol.

Ich habe so viele menschliche Instanzen wie die Anzahl der Argumente erstellt und bestätigt, dass die Methode ausgeführt wurde.

Paketverwaltung

Geben Sie ihm einen Paketnamen und versuchen Sie, ihn als Programm in einem separaten Paket zu kompilieren. Geben Sie der Klasse Human zunächst einen Paketnamen. Da auf diese Klasse von einem anderen Paket aus zugegriffen wird, habe ich jeden Modifikator korrekt hinzugefügt.

Human.java


package jp.co.sample.lib;

public class Human {
    private String name;
    public Human(String name) {
        this.name = name;
    }
    public void introduceMyself() {
        System.out.println(String.format("My name is %s.", this.name));
    }
}

Geben Sie als Nächstes für die App-Klasse den Paketnamen an und beschreiben Sie den Import für den Zugriff auf die Human-Klasse.

App.java


package jp.co.sample;

import jp.co.sample.lib.Human;

class App {
    public static void main(String[] args) {
        for (String arg: args) {
            Human human = new Human(arg);
            human.introduceMyself();
        }
    }
}

Der Paketname wurde zugewiesen, kann jedoch nicht so kompiliert werden, wie er ist. In Java müssen die Dateien in derselben Verzeichnisstruktur wie der Paketname angeordnet werden. Erstellen Sie also ein Verzeichnis wie unten gezeigt und verschieben Sie die Dateien.

$ tree
.
└── jp
    └── co
        └── sample
            ├── App.java
            └── lib
                └── Human.java

4 directories, 2 files

Kompilieren Sie die Datei nach dem Verschieben und führen Sie sie aus.

$ javac jp/co/sample/App.java

$ tree
.
└── jp
    └── co
        └── sample
            ├── App.class
            ├── App.java
            └── lib
                ├── Human.class
                └── Human.java

4 directories, 4 files

$ java jp.co.sample.App Alice Bob Carol
My name is Alice.
My name is Bob.
My name is Carol.

Es wurde bestätigt, dass die .class-Datei auf derselben Ebene wie jede .java-Datei erstellt wurde und das Programm ausgeführt werden konnte.

Erstellen einer JAR-Datei

Kombinieren Sie die erstellten ".class" -Dateien zu ".jar" und erstellen Sie ein Archiv. Die .java-Datei ist nicht in .jar enthalten. Trennen Sie sie daher als src-Verzeichnis.

$ tree
.
└── src
    └── jp
        └── co
            └── sample
                ├── App.java
                └── lib
                    └── Human.java

5 directories, 2 files

Kompilieren Sie die .class-Datei und geben Sie sie in das Klassenverzeichnis aus. Wenn Sie an einem anderen Speicherort als dem Verzeichnis src für den Paketursprung ausgeführt werden möchten, müssen Sie den Paketursprung mit der Option -sourcepath angeben.

$ javac -sourcepath src -d classes src/jp/co/sample/App.java 

$ tree
.
├── classes
│   └── jp
│       └── co
│           └── sample
│               ├── App.class
│               └── lib
│                   └── Human.class
└── src
    └── jp
        └── co
            └── sample
                ├── App.java
                └── lib
                    └── Human.java

10 directories, 4 files

Sie können sehen, dass das Klassenverzeichnis erstellt wurde und die ".class" -Dateien darunter mit derselben Verzeichnisstruktur wie das Paket erstellt wurden. Übrigens, wenn Sie zur Laufzeit an einem anderen Ort als dem Paketursprung ausführen möchten, müssen Sie den Paketursprung mit der Option "-classpath" angeben.

$ java -classpath classes jp.co.sample.App Alice Bob Carol
My name is Alice.
My name is Bob.
My name is Carol.

Als nächstes muss die MANIFEST-Datei ".jar" erstellen. Erstellen Sie daher die folgende Datei. Der Name der Klasse mit der Hauptmethode wird hier beschrieben, einschließlich des Paketnamens. Vergessen Sie nicht, dass eine leere Zeile in der letzten Zeile nicht als MANIFEST-Datei erkannt wird.

manifest.mf


Main-Class: jp.co.sample.App

Erstellen Sie nach dem Vorbereiten der MANIFEST-Datei eine .jar-Datei mit jar.

$ jar cvfm sample.jar manifest.mf -C classes .
Manifest hinzugefügt
jp/Wird hinzugefügt(Eingeben=0)(aus=0)(0%Gelagert)
jp/co/Wird hinzugefügt(Eingeben=0)(aus=0)(0%Gelagert)
jp/co/sample/Wird hinzugefügt(Eingeben=0)(aus=0)(0%Gelagert)
jp/co/sample/App.Klasse wird hinzugefügt(Eingeben=469)(aus=343)(26%Schrumpfte)
jp/co/sample/lib/Wird hinzugefügt(Eingeben=0)(aus=0)(0%Gelagert)
jp/co/sample/lib/Human.Klasse wird hinzugefügt(Eingeben=595)(aus=382)(35%Schrumpfte)

$ ls
classes  manifest.mf  sample.jar  src

$ jar -tf sample.jar 
META-INF/
META-INF/MANIFEST.MF
jp/
jp/co/
jp/co/sample/
jp/co/sample/App.class
jp/co/sample/lib/
jp/co/sample/lib/Human.class

Sie können sehen, dass die .jar-Datei die MANIFEST-Datei und die .class-Datei enthält. Lassen Sie uns abschließend die .jar-Datei ausführen.

$ java -jar sample.jar Alice Bob Carol
My name is Alice.
My name is Bob.
My name is Carol.

Zusammenfassung

In diesem Artikel habe ich ein Programm geschrieben, es kompiliert und dann eine .jar-Datei erstellt und ausgeführt. Möglicherweise haben Sie das Gefühl, dass der Arbeitsinhalt zwischen dem Arbeiten in der IDE und dem Drücken von Befehlen in der CLI zum Kompilieren und Ausführen sehr unterschiedlich ist. Während Sie in einer IDE mit einer Benutzeroberfläche intuitiv arbeiten können, müssen Sie jeden Befehl in der CLI verstehen und ausführen. Ich denke, dass das Verständnis des Inhalts dieses Artikels Ihnen auch hilft, die Arbeit in IDE zu verstehen.

Bonus

OpenJDK enthält ein Tool, mit dem die kompilierte ".class" -Datei umgekehrt zusammengestellt werden kann. Sie können der detaillierten Anweisung des Programms folgen. Wenn Sie es sich leisten können, sollten Sie einen Blick darauf werfen.

$ javap -v -classpath classes jp.co.sample.App
Classfile /home/vagrant/java_test/classes/jp/co/sample/App.class
  Last modified 2019/04/30; size 469 bytes
  MD5 checksum 7ad6f96dd09200ac12a4c48cadb71ea8
  Compiled from "App.java"
class jp.co.sample.App
  minor version: 0
  major version: 54
  flags: (0x0020) ACC_SUPER
  this_class: #5                          // jp/co/sample/App
  super_class: #6                         // java/lang/Object
  interfaces: 0, fields: 0, methods: 2, attributes: 1
Constant pool:
   #1 = Methodref          #6.#17         // java/lang/Object."<init>":()V
   #2 = Class              #18            // jp/co/sample/lib/Human
   #3 = Methodref          #2.#19         // jp/co/sample/lib/Human."<init>":(Ljava/lang/String;)V
   #4 = Methodref          #2.#20         // jp/co/sample/lib/Human.introduceMyself:()V
   #5 = Class              #21            // jp/co/sample/App
   #6 = Class              #22            // java/lang/Object
   #7 = Utf8               <init>
   #8 = Utf8               ()V
   #9 = Utf8               Code
  #10 = Utf8               LineNumberTable
  #11 = Utf8               main
  #12 = Utf8               ([Ljava/lang/String;)V
  #13 = Utf8               StackMapTable
  #14 = Class              #23            // "[Ljava/lang/String;"
  #15 = Utf8               SourceFile
  #16 = Utf8               App.java
  #17 = NameAndType        #7:#8          // "<init>":()V
  #18 = Utf8               jp/co/sample/lib/Human
  #19 = NameAndType        #7:#24         // "<init>":(Ljava/lang/String;)V
  #20 = NameAndType        #25:#8         // introduceMyself:()V
  #21 = Utf8               jp/co/sample/App
  #22 = Utf8               java/lang/Object
  #23 = Utf8               [Ljava/lang/String;
  #24 = Utf8               (Ljava/lang/String;)V
  #25 = Utf8               introduceMyself
{
  jp.co.sample.App();
    descriptor: ()V
    flags: (0x0000)
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 5: 0

  public static void main(java.lang.String[]); 
    descriptor: ([Ljava/lang/String;)V
    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
    Code:
      stack=3, locals=6, args_size=1
         0: aload_0
         1: astore_1
         2: aload_1
         3: arraylength
         4: istore_2
         5: iconst_0
         6: istore_3
         7: iload_3
         8: iload_2
         9: if_icmpge     39
        12: aload_1
        13: iload_3
        14: aaload
        15: astore        4
        17: new           #2                  // class jp/co/sample/lib/Human
        20: dup
        21: aload         4
        23: invokespecial #3                  // Method jp/co/sample/lib/Human."<init>":(Ljava/lang/String;)V
        26: astore        5
        28: aload         5
        30: invokevirtual #4                  // Method jp/co/sample/lib/Human.introduceMyself:()V
        33: iinc          3, 1
        36: goto          7
        39: return
      LineNumberTable:
        line 7: 0
        line 8: 17
        line 9: 28
        line 7: 33
        line 11: 39
      StackMapTable: number_of_entries = 2
        frame_type = 254 /* append */
          offset_delta = 7
          locals = [ class "[Ljava/lang/String;", int, int ]
        frame_type = 248 /* chop */
          offset_delta = 31
}
SourceFile: "App.java"

Recommended Posts

Java-Kompilierung und Ausführung von CLI verstanden
Ausführung durch Subshell (und Variablenaktualisierung)
Fehler und Abschluss der Ausführung durch LINE [Python] benachrichtigen
pytube Ausführung und Fehler
Verstehen Sie das Decorator-Muster, indem Sie JavaScript und Java-Code vergleichen
Verstehen Sie das Statusmuster, indem Sie JavaScript und Java-Code vergleichen
Verstehen Sie das zusammengesetzte Muster, indem Sie JavaScript und Java-Code vergleichen
Unterschied zwischen Vordergrundprozess und Hintergrundprozess, prinzipiell verstanden