Java Tipp 131: Geben Sie eine Erklärung mit javac ab!

Oft möchten Sie vielleicht einen einzelnen Code testen. Angenommen, Sie vergessen, wie der %Operator mit negativen Zahlen arbeitet, oder Sie müssen festlegen, wie ein bestimmter API-Aufruf funktioniert. Das wiederholte Schreiben, Kompilieren und Ausführen eines kleinen Programms, nur um kleine Dinge zu testen, kann sich als ärgerlich erweisen.

In diesem Sinne stelle ich in diesem Java-Tipp ein kurzes Programm vor, das Java-Code-Anweisungen einfach mithilfe von Tools kompiliert und ausführt, die in JDK 1.2 und höher von Sun enthalten sind.

Hinweis: Sie können den Quellcode dieses Artikels von Resources herunterladen.

Verwenden Sie Javac in Ihrem Programm

Sie finden den javacCompiler in der tools.jarBibliothek im lib/Verzeichnis Ihrer JDK 1.2- und höheren Installation.

Viele Entwickler erkennen nicht, dass eine Anwendung javacprogrammgesteuert zugreifen kann . Eine aufgerufene Klasse com.sun.tools.javac.Mainfungiert als Haupteinstiegspunkt. Wenn Sie wissen, wie man javacin der Befehlszeile verwendet, wissen Sie bereits, wie diese Klasse verwendet wird: Ihre compile()Methode verwendet die bekannten Befehlszeilen-Eingabeargumente.

Kompilieren Sie eine einzelne Anweisung

Um javaceine Anweisung zu kompilieren, muss die Anweisung in einer vollständigen Klasse enthalten sein. Definieren wir jetzt eine minimale Klasse:

 / ** * Quelle erstellt am * / public class {public statisch void main (String [] args) löst eine Ausnahme aus {}} 

Können Sie herausfinden, warum die main()Methode eine Ausnahme auslösen muss?

Ihre Aussage geht offensichtlich main()wie gezeigt in die Methode ein, aber was sollten Sie für den Klassennamen schreiben? Der Klassenname muss denselben Namen haben wie die Datei, in der er enthalten ist, da wir ihn als deklariert haben public.

Bereiten Sie eine Datei für die Kompilierung vor

Zwei Einrichtungen, die java.io.Fileseit JDK 1.2 in der Klasse enthalten sind, helfen. Die erste Möglichkeit, temporäre Dateien zu erstellen, befreit uns von der Auswahl eines temporären Namens für unsere Quelldatei und Klasse. Es garantiert auch die Eindeutigkeit des Dateinamens. Verwenden Sie die statische createTempFile()Methode, um diese Aufgabe auszuführen .

Mit der zweiten Funktion, bei der eine Datei beim Beenden der VM automatisch gelöscht wird, können Sie vermeiden, dass ein Verzeichnis oder Verzeichnisse mit temporären kleinen Testprogrammen überfüllt sind. Sie legen eine Datei zum Löschen fest, indem Sie aufrufen deleteOnExit().

Erstellen Sie die Datei

Wählen Sie die createTempFile()Version aus, mit der Sie den Speicherort der neuen Datei angeben können, anstatt sich auf ein temporäres Standardverzeichnis zu verlassen.

Geben Sie abschließend an, dass die Erweiterung .javaund das Dateipräfix sein müssen jav(die Präfixauswahl ist beliebig):

Datei file = File.createTempFile ("jav", ".java", neue Datei (System.getProperty ("user.dir"))); // Setze die zu löschende Datei beim Beenden file.deleteOnExit (); // Den Dateinamen abrufen und einen Klassennamen daraus extrahieren String filename = file.getName (); String classname = filename.substring (0, filename.length () - 5);

Beachten Sie, dass Sie den Klassennamen extrahieren, indem Sie das .javaSuffix entfernen .

Geben Sie die Quelle mit Ihrem Funktionscodesegment aus

Schreiben Sie als Nächstes den Quellcode PrintWriterzur Vereinfachung in die Datei :

PrintWriter out = neuer PrintWriter (neuer FileOutputStream (Datei)); out.println ("/ **"); out.println ("* Quelle erstellt am" + neues Datum ()); out.println ("* /"); out.println ("öffentliche Klasse" + Klassenname + "{"); out.println ("public static void main (String [] args) löst eine Ausnahme aus {"); // Dein Shortcode-Segment out.print (""); out.println (text.getText ()); out.println ("}"); out.println ("}"); // Leere und schließe den Stream out.flush (); out.close ();

Der generierte Quellcode sieht für eine spätere Prüfung gut aus, mit dem zusätzlichen Vorteil, dass wenn die VM abnormal beendet wird, ohne die temporäre Datei zu löschen, die Datei kein Rätsel ist, wenn Sie später darauf stoßen.

Wenn Sie bemerken, wird das Funktionscodesegment mit geschrieben text.getText(). Wie Sie in Kürze sehen werden, verwendet das Programm eine kleine grafische Benutzeroberfläche (GUI), und Ihr gesamter Code wird in einen TextAreaaufgerufenen Code eingegeben text.

Verwenden Sie Javac zum Kompilieren

Um den Compiler zu verwenden, erstellen Sie Mainwie oben erwähnt eine Objektinstanz. Verwenden wir ein Instanzfeld, um dies zu speichern:

 private com.sun.tools.javac.Main javac = new com.sun.tools.javac.Main (); 

Ein Aufruf von compile()mit einigen Befehlszeilenargumenten kompiliert die oben genannte Datei. Außerdem wird ein Statuscode zurückgegeben, der entweder den Erfolg oder ein Problem bei der Kompilierung anzeigt:

String [] args = new String [] {"-d", System.getProperty ("user.dir"), Dateiname}; int status = javac.compile (args);

Führen Sie das frisch kompilierte Programm aus

Reflection führt Code in einer beliebigen Klasse aus, sodass wir ihn verwenden, um die main()Methode zu finden und auszuführen , in der wir unser Kurzcodesegment platziert haben. Darüber hinaus verarbeiten wir den zurückgegebenen Statuscode, indem wir eine entsprechende Nachricht anzeigen, um den Benutzern eine saubere und informative Erfahrung zu bieten. Wir haben die Bedeutung jedes Statuscodes durch Dekompilieren gefunden javac, daher haben wir diese seltsamen " Status kompilieren " -Nachrichten.

Die eigentliche Klassendatei befindet sich im aktuellen Arbeitsverzeichnis des Benutzers, wie bereits mit der -dOption für die javacInstanz angegeben.

Ein 0Statuscode zeigt an, dass die Kompilierung erfolgreich war:

switch (status) {case 0: // OK // Erstelle die Klassendatei auch als neue Datei (file.getParent (), Klassenname + ".class"). deleteOnExit (); try {// Versuchen Sie, auf die Klasse zuzugreifen und ihre Hauptmethode auszuführen. Class clazz = Class.forName (classname); Methode main = clazz.getMethod ("main", neue Klasse [] {String []. Klasse}); main.invoke (null, neues Objekt [] {neuer String [0]}); } catch (InvocationTargetException ex) {// Ausnahme in der Hauptmethode Wir haben gerade versucht, showMsg auszuführen ("Exception in main:" + ex.getTargetException ()); ex.getTargetException (). printStackTrace (); } catch (Ausnahme ex) {showMsg (ex.toString ()); } Unterbrechung; Fall 1: showMsg ("Kompilierungsstatus: FEHLER"); Unterbrechung; Fall 2: showMsg ("Kompilierungsstatus: CMDERR"); Unterbrechung; Fall 3: showMsg ("Kompilierungsstatus: SYSERR"); Unterbrechung; Fall 4: showMsg ("Kompilierungsstatus:ABNORMAL "); break; Standard: showMsg (" Kompilierungsstatus: Unbekannter Exit-Status ");}

Ein InvocationTargetExceptionWurf, wenn Code durch Reflektion ausgeführt wird und der Code selbst eine Ausnahme auslöst. In diesem Fall wird der InvocationTargetExceptionStack-Trace der zugrunde liegenden Ausnahme abgefangen und auf der Konsole gedruckt. Alle anderen wichtigen Nachrichten werden an eine showMsg()Methode gesendet, an die der Text einfach weitergeleitet wird System.err.

Die Nicht-OK-Statuscodes (andere Codes als Null) führen dazu, dass eine kurze Fehlermeldung angezeigt wird, um den Benutzer darüber zu informieren, was passiert, wenn ein Kompilierungsproblem auftritt.

Wie man das Programm benutzt

Ja, das war's! Abgesehen von einer schönen Benutzeroberfläche und einem eingängigen Namen ist der Kern des Programms vollständig. Das Programm mit einer kleinen AWT-Schnittstelle (Abstract Windowing Toolkit) zur Eingabe sendet alle Ausgaben System.erran die Konsole (oder an einen beliebigen Ort, an dem Sie sie durch Ändern der showMsg()Methode senden möchten).

So, what about a catchy name for the program? How about JavaStatement? It's concise, to the point, and so boring nobody would think it was chosen this way on purpose. Henceforth, all references to "the program" or "the application" will be replaced by "JavaStatement."

Write statements

Statements sometimes must be written a certain way, and you must take special care to run the JVM with the proper classpath. I elaborate on these issues below:

  • If you use packages other than java.lang, you may notice the absence of import statements at the top of the generated source code. You may wish to add a few convenient imports such as java.io or java.util to save some typing.
  • If you do not add any imports, then for any class outside java.lang, you must prepend the full package name. For example, to create a new java.util.StringTokenizer, use new java.util.StringTokenizer(...) instead of just new StringTokenizer(...).

Screenshot

The figure below shows JavaStatement's GUI, with its text area for typing statements and a Run button for executing the code. All output goes to System.err, so watch the window from where the program runs.

Run the program

JavaStatement references two classes that may not otherwise be included in the JVM's classpath: the com.sun.tools.javac.Main class from tools.jar and the temporary compiled classes situated in the current working directory.

Thus, to run the program properly, use a command line such as:

 java -cp /lib/tools.jar;. JavaStatement 

where represents your JDK's installed location.

For example, I installed my JDK to C:\Java\jdk1.3.1_03. Hence, my command line would be:

 java -cp C:\java\jdk1.3.1_03\lib\tools.jar;. JavaStatement 

Note: You must also include the tools.jar library in the classpath when compiling JavaStatement.java.

If you forget to add the tools.jar file to your classpath, you'll find complaints either about a NoClassDefFoundError for the JVM or an unresolved symbol for the compiler.

Finally, compile the JavaStatement.java with the same compiler version that runs the code.

Test short bits of code? No problem!

Java developers frequently test short bits of code. JavaStatement lets you efficiently test such code by freeing you from tediously going through the cycle of writing, compiling, and running many small programs.

Beyond JavaStatement, perhaps challenge yourself by exploring how to use javac in your own programs. Off the top of my head, I can think of two javac uses:

  1. A rudimentary form of scripting: Coupled with using your own classloader, you could make the compiled classes reference objects from within a running program
  2. A programming language translator: It is simpler to translate a program (say written in Pascal) into Java, and compile it into classfiles, than to compile it yourself

Remember, javac does the hard work of translating a high-level language into low-level instructions—freeing you to do your own thing with Java!

Shawn Silverman ist Doktorand am Institut für Elektrotechnik und Informationstechnik der Universität von Manitoba, Kanada. Er begann Mitte 1996 mit Java zu arbeiten und verwendet es seitdem fast ausschließlich. Seine aktuellen Interessen umfassen die Simulation elektrischer Felder und Flüssigkeiten, eingebettetes Java und die Implementierung von raffinierten GUI-Tricks. Shawn unterrichtet auch einen Software-Design-Kurs im dritten Jahr in der Abteilung für Computertechnik an seiner Universität.

Erfahren Sie mehr über dieses Thema

  • Um das Programm dieses Artikels herunterzuladen, gehen Sie zu

    //images.techhive.com/downloads/idge/imported/article/jvw/2002/08/jw-javatip131.zip

  • Weitere Informationen zum Javac-Compiler finden Sie auf der Seite "Javac - Der Java-Compiler"

    //java.sun.com/products/jdk/1.1/docs/tooldocs/solaris/javac.html

  • "The Reflection API" trail by Dale Green in Sun Microsystems' Java Tutorial (Sun Microsystems, 2002)

    //java.sun.com/docs/books/tutorial/reflect/index.html

  • The Javadoc for java.lang.reflect

    //java.sun.com/j2se/1.3/docs/api/java/lang/reflect/package-summary.html

  • Read "A Java Make Tool for the Java Language" (the tool uses javac as we have in this article)

    //www.experimentalstuff.com/Technologies/JavaMake/index.html

  • Browse the Development Tools section of JavaWorld's Topical Index

    //www.javaworld.com/channel_content/jw-tools-index.shtml

  • View all previous Java Tips and submit your own

    //www.javaworld.com/javatips/jw-javatips.index.html

  • Learn Java from the ground up in JavaWorld's Java 101 column

    //www.javaworld.com/javaworld/topicalindex/jw-ti-java101.html

  • Java experts answer your toughest Java questions in JavaWorld's Java Q&A column

    //www.javaworld.com/javaworld/javaqa/javaqa-index.html

  • Stay on top of our Tips 'N Tricks by subscribing to JavaWorld's free weekly email newsletters

    //www.javaworld.com/subscribe

  • Learn the basics of client-side Java in JavaWorld's Java Beginner discussion. Core topics include the Java language, the Java Virtual Machine, APIs, and development tools

    //forums.idg.net/[email protected]@.ee6b804

  • Unter .net finden Sie eine Fülle von IT-Artikeln aus unseren Schwesterpublikationen

Diese Geschichte, "Java Tipp 131: Geben Sie eine Erklärung mit javac ab!" wurde ursprünglich von JavaWorld veröffentlicht.