[edit SlaterB: Thema abgespalten, Zitat hinzugefügt]
Java ist keine Interpretersprache…
[edit SlaterB: Thema abgespalten, Zitat hinzugefügt]
Java ist keine Interpretersprache…
Java wird sowohl compiliert wie auch Bytecode interpretiert, einigen wir uns darauf.
Der Bytecode wird aber nicht interpretiert, sondern genau wie Maschinencode direkt ausgeführt. Im Gegensatz zu Maschinencode wird er allerdings durch eine virtuelle Maschine, die JVM, ausgeführt und nicht direkt durch einen physikalischen Prozessor.
Ist hier im Thread aber alles OT.
[QUOTE=cmrudolph]Java ist keine Interpretersprache…
[…]
Der Bytecode wird aber nicht interpretiert, sondern genau wie Maschinencode direkt ausgeführt. Im Gegensatz zu Maschinencode wird er allerdings durch eine virtuelle Maschine, die JVM, ausgeführt und nicht direkt durch einen physikalischen Prozessor.[/QUOTE]
[ot]Ich sag es echt nur ungern, aber leider falsch !
Java wurde ursprünglich als reine Interpreter-Sprache erdacht und auch so entwickelt. Oder - um mal böse zu sein: Wie genau würdest du es sonst bezeichnen dass der Byte-Code durch eine „virtuelle“ Umgebung ausgeführt und auf die reale Platform „übersetzt“ wird?
Guck dir doch mal die Ausgabe von java -X
an. Eine der Möglichen Parameter ist -Xint Nur Ausführung im interpretierten Modus
. Dies ist eine Rückwärtskompatibilität zu alten 1.x Versionen der ursprünglichen JVM-Spec von Sun.
Der heute oft verwendete Just-in-Time-native-compiler ist eine Zusätzliche „Funktion“ die erst später hinzugefügt wurde. Und auch ist es VM-spezifisch wie viel vom Byte-Code wirklich in native-Code übersetzt wird (unter anderem wie oft z.B. ein Loop ausgeführt oder ein bestimmter Code-Abschnitt wiederholend aufgerufen wird).
Ein weiterer Parameter ist: -Xmixed Ausführung im gemischten Modus (Standard)
. Schon alleine diese Beschreibung erklärt die „normale“ Arbeitsweise einer typischen JVM: Es wird grundsätzlich erstmal rein interpretierend gearbeitet und erst nach und nach unter bestimmten Umständen gewissen Code-Teile in native-Code optimiert um die Performance zu steigern.
Um nur eine Quelle zu nennen: https://en.wikipedia.org/wiki/Java_(programming_language)
However, the overhead of interpreting bytecode into machine instructions makes interpreted programs almost always run more slowly than native executables. However, just-in-time (JIT) compilers that compile bytecodes to machine code during runtime were introduced from an early stage.
Ich will nicht ins Detail gehen, aber ich bin sicher dass man in weiteren Quellen genau dies so erklärt bekommt. Gleich ob die JSR oder halt von irgendwelchen Autoren als „erklärendes Werk“.
Ergo: CB hat soweit mit seinem Post recht: Byte-Code wird (zu erst) sowohl rein durch die VM interpretiert - als auch durch HotSpot zur Runtime in native-Code der tatsächlichen Hardware optimiert.[/ot]
Naja…
„Java ist keine Interpretersprache“ ist vollkommen richtig, denn Java wird nicht interpretiert, sondern kompiliert
Wie du richtig bechreibst wird Bytecode wird meist interpretiert, manchmal kompiliert, aber das ist ein Implementierungsdetail der JVM und macht Java sicherlich nicht zu einer „Interpreter Sprache“.
[ot]Gut, und was genau wird dann mit dem Ergebnis (Kompilat) nach dem Kompilieren gemacht? Richtig: es wird (vorerst vollständig) interpretiert. Und dies ist auch nicht “meist” der Fall, sondern beim ersten Durchlauf grundsätzlich IMMER. Denn die native-Optimierung erfolgt, wie geschrieben, erst zur Runtime unter bestimmten Kreterien.
Als blödes Beispiel: Habe ich einen Code mit einem Loop der bei einer Ausführung genau ein mal durchläuft ist es sehr unwahrscheinlich das dieses Code-Stück native-optimiert wird. Wird die Zeile aber zig-tausende mal durchlaufen ist es schon sehr viel wahrscheinlicher das irgendwann eine native-Optimierung greift. Die Häufigkeit wie oft eine bestimmte Code-Zeile gecallt wird ist ja auch nur einer der möglichen Kreterien. Andere können z.B. sein wie gut sich der Code überhaupt optimieren lässt. Habe ich im Source ein einfaches post-Inkrement wird dies sicher bereits durch den Compiler so optimiert das es möglichst direkt vom physischen CPU ausgeführt wird. Habe ich aber so ein bit-Geschubse wie ein String.concat() habe (Beispiel) wird es sicher mehrere Möglichkeiten der Optimierung geben.
Ergo: Java ist sehr wohl eine ursprünglich reine interpretierte Sprache, wenngleich der Sinn-laut nicht mit z.B. Perl, PHP oder JavaScript vergleichbar ist. Wobei, gerade wenn man sich PHP ansieht passiert dort ähnliches, und trotzdem wird PHP von vielen ganz klar als “reine” Interpreter-Sprache bezeichnet - auch wenn dort bereits sehr früh JIT-Compiler Einzug gehalten haben.
//EDIT
Anderes Beispiel:
Gehen wir mal von aus Java wäre keine Interpreter-Sprache, würde dies im Umkehrschluss irgendwie bedeuten das der normale ahead-of-time-compiler bereits native-code in den Byte-Code einbauen würde. Alleine DAS widerspricht schon einem der Java-Grundsätze “compile once, run everwhere”. Denn ein Intel-x86 increment sieht ganz anders aus als z.B. ein ARM increment. Die VM müsste also erstmal mitbekommen das da ein native-Code drin steckt der gar nicht zur Zielplatform passt und dies dann erst wieder umbauen.
Es geht also schlicht nicht. Und das macht, IMO, Java zu einer Interpreter-Sprache.[/ot]
Sen-Mithrarin, ich kann mich nur wiederholen, du hast Unrecht, Java wird compiliert, nicht interpretriert, Bytecode wiederum ist eine andere Geschichte…
@maki wieso so einsilbige Antworten? die klassische Sicht von Kompilieren zu Maschinencode ist es auf keinen Fall,
einfach nur diesen Satz ohne längere Erklärungen, das ist in jedem Fall falsch
genauso ist es aber keine reine Interpretation nach klassischer Defintion, der Java-Fall ist in der Kategorisierung der beiden Begriffe nicht vorgesehen,
steht auch etwa hier (wenn auch nicht unbedingt Hammer-Quelle )
https://www.c64-wiki.de/index.php/Unterschiede_zwischen_Assembler,_Interpreter_und_Compiler
als Hybrid
was ist Kompilieren? Umwandlung von Hochsprache in fertigen Maschinenbefehle, die ohne jede Kontrollstruktur direkt vom Prozessor ausgeführt wird
(wenn ich falsch liege dann korrigieren )
davon ist Java eindeutig meilenweit entfernt, weder Quellcode noch Bytecode kann für sich alleine auch nur einen Millimeter ausgeführt werden,
es braucht eine gigantische komplexe Software zur Ausführung, von der API ganz abgesehen,
was ist Interpreter?
eben diese komplexe virtuelle Maschine zur Ausführung des Quellcodes,
wobei der Link oben eine ‚effizientere Zwischendarstellung mittels Token‘ gestattet oder auch
gar von
Viele interpretierte Sprachen verwenden auch intern Bytecode. Das bedeutet, dass der Bytecode an sich unsichtbar für den Programmierer und Endbenutzer gehalten wird und automatisch als Zwischenschritt der Interpretation des Programmes erzeugt wird. Beispiele für aktuelle Sprachen, die diese Technik verwenden, sind: Perl, PHP, Prolog, Tcl und Python. In Python wird der Bytecode nach dem ersten Parsen in .pyc-Dateien (welche den Bytecode enthalten) abgelegt; das Vorgehen ähnelt damit prinzipiell dem bei Java. Dieser Schritt ist jedoch optional.
spricht
was spräche dagegen, einer JVM den Java-Quellcode direkt zu geben? sie könnte bis auf Effizienzfragen und paar Sonderproblemchen im Prinzip genauso gut selber kompilieren,
man bräuchte über Bytecode gar nicht groß zu reden,
Java ist schon sehr sehr sehr nahe an einer Interpretersprache,
und gigantisch weit entfernt von einer Compiler-Sprache mit Assembler-Code, hat damit absolut gar nix zu tun,
aber man kann all das natürlich ignorieren und schlicht nach der Definition gehen, Java ist Compiler-Sprache, fertig
jedem das seine
[QUOTE=SlaterB]
jedem das seine[/QUOTE]
Ein Godwin Punkt für dich!!!111elf
Ich bin auch darüber gestolpert, als dieser Satz im anderen Thread auftauchte. Bin dann aber davon ausgegangen, dass das ironisch-„trollhaft“-„provokativ“ gemeint war.
Vielleicht auch nicht?
Ich denke, diese Abgrenzung zwischen Compiler und Interpreter ist zwar theoretisch sehr strikt möglich, aber in der Realität sind die Grenzen eben fließend. Eigentlich würde ich jetzt noch erwähnen, dass „Interpretierte Sprache“ und „Compilierte Sprache“ nur bedingt Sinn machen, weil man sowohl Java in echten x86-Maschinencode, als auch C in Java Bytecode übersetzen kann, aber das ist nur eine der möglichen (an Wortklauberei grenzenden) Ausdifferenzierungen.
Unabhängig davon: Wenn man jetzt einen Chip baut, dessen Instruktionssatz genau dem Java Bytecode entspricht, ist Java dann Interpretiert oder Compiliert, und ist der Bytecode dann Interpretiert oder nicht? Und wenn man auf so einer JM (also JVM ohne V) dann einen Emulator für eine x86-Maschine laufen läßt, ist dann der x86-Maschinencode interpretiert?
Wie auch immer, ich denke, das ist keine Diskussion, wo am ende ein „konkretes Ergebnis“ oder eine „Einigung“ stehen kann. Es kann nur jeder seine (hoffentlich für andere interessanten) Denk- und Sichtweisen äußern, Fragen in den Raum stellen, oder zum Nachdenken anregen.
Und falls jemand gerne mal sein Gehirn richtig verknoten will, der kann sich mit den drei Futamura-Projektionen beschäftigen (und darüber nachdenken, ob es noch eine vierte, fünfte oder sechste gibt :sick: ).
Wenn man sich den Befehlssatz der JVM in der JVMS ansieht, dann deckt sich das zu einem guten Teil mit den Befehlen eines physikalischen Prozessors. Nicht umsonst heißt es „Virtual Machine“.
Der Bytecode stellt daher „fertige Maschinenbefehle“ dar. Es gibt Java-Prozessoren, die den Bytecode als Maschinensprache implementieren.
Nur weil der gängige „Prozessor“, der Bytecode ausführt, eine virtuelle Maschine ist, heißt das doch noch lange nicht, dass der Bytecode deshalb interpretiert wird. Zumindest sehe ich das so.
Wenn dem nicht so wäre, dann wäre z. B. C auch eine Interpretersprache. Denn ein Compiler, der eine ausführbare Binärdatei (exe, elf, etc…) erzeugt**, erzeugt eine Datei, die auch von einer rein in Software implementierten CPU (Virtualisierte CPU ohne Hardwareunterstützung) ausgeführt (und demnach „interpretiert“) werden kann.
[HR][/HR]
Abgesehen davon hat @maki Recht damit, dass Bytecode und Java unabhängig voneinander existieren können. Es gibt schließlich auch Compiler, die von anderen Sprachen in Bytecode übersetzen (Scala als prominentestes Beispiel).
Sehe ich anders. Vergleiche mal den Befehlssatz der JVM mit einem gängigen Assembler-Dialekt* und du wirst erstaunlich viele Parallelen finden.
*** Edit ***
Mein Beitrag hat sich jetzt mit dem von @Marco13 überschnitten. Der Argumentationskette kann ich nur zustimmen.
interessante weitere Sicht, Bytecode als Maschinenbefehle stand bisher glaube ich hier noch nicht so deutlich,
wobei das nur immer weiter vermischt, genauso könnte für jede andere Interpretationssprache ein passender Prozessor gebaut werden
oder gibt es klare strukturelle Unterschiede?
mal sehen ob maki dem auch zustimmt
ist das nun nicht erstaunliche klare Falschaussage, Bytecode absolut plattformunabhängig, fertige .class-Dateien für alle Systeme passend zu bekommen?
Die Java Virtual Machine ist dazu da, den vom Java-Compiler erzeugten (plattformunabhängigen) Bytecode plattformabhängig auszuführen.
dass es normalerweise eine JVM braucht um auf einem bestimmten System die Verbindung/ Abhängigkeit zur Plattform herzustellen, dieser Schritt ist auszuklammern?
im Gegensatz zu anderen Programmiersprachen
oder evtl. weil generell alle (imperativen) Programmiersprachen die gleichen Dinge wie Addition, Variablenzuweisung, Methodenaufruf usw. enthalten und sich ähneln?
Bytecode ist in dem Sinne sehr wohl plattformabhängig, weil er nicht direkt von einer x86-CPU ausgeführt werden kann, sondern nur von einer JVM / Hardware, die eben den Bytecode als „Maschinensprache“ implementiert.
Das meinte ich mit der Analogie zum Assembler - dort gibt es ebenso Unterschiede, je nachdem, welche Zielplattform man anvisiert.
*** Edit ***
Der Befehlssatz kennt aber „Variablen“ im hochsprachlichen Sinne gar nicht. Viel mehr nur im Sinne von Registern (wie bei echtem Maschinencode auch): es gibt nur durchnummerierte Speicherplätze.
Methodenaufrufe etc. sind dort genauso umgesetzt, wie direkt in einer CPU auch. Mittels Sprunganweisung und dem Ablegen von Werten auf einem Stack.
Will sagen: der Bytecode ist deutlich näher an Maschinencode, als an einer Hochsprache.
[quote=cmrudolph]Bytecode ist in dem Sinne sehr wohl plattformabhängig, weil er nicht direkt von einer x86-CPU ausgeführt werden kann, sondern nur von einer JVM / Hardware, die eben den Bytecode als „Maschinensprache“ implementiert.
Das meinte ich mit der Analogie zum Assembler - dort gibt es ebenso Unterschiede, je nachdem, welche Zielplattform man anvisiert.[/quote]
nun ja, wenn die JVM die Plattform ist, die einzige denkbare Plattform, dann erübrigt sich die Unterscheidung in abhängig/ unabhängig irgendwie…,
es gibt jedenfalls nur einen Bytecode
Zitat von Marco13, aber allgemein an alle gefragt:
wie steht es eigentlich mit Dingen wie StackTrace (StackOverflow!), Threads, GarbageCollector, Speichermanagement (OutOfMemory),
Sicherheit des Speichers vor Fremdzugriff, vor Bufferüberlauf usw.,
ist das alles unabhängig von einer ausführenden JVM, wäre das bei reinen Assembler-Programmen auch möglich
(natürlich bei entsprechenden Aufbau, aber Java anders geplant mit JVM? oder in der API hinterlegt?)
oder steht die interpretierende Ausführung mit Big Brother JVM drumherum für diese oder ähnliche Features?
müsste/ bietet ein Java-Prozessor in dieser Hinsicht weitaus mehr als ein normaler Prozessor,
von dem ich grob nicht mehr als paar Grundbefehle (ALU), prozessornahe Speicherpläze (Register) und sonst völlige Ignoranz zum Programm und Arbeitsspeicher in Erinnerung habe,
alles nur Speicheradressen und Bytes, der nächste Befehl mag sein was will, keinerlei Kontrolle/ Meinung/ Zustand
ein Thread-Wechsel ist doch eine komplizierte Folge von hunderten Befehlen, wo steht der Code dazu?
[OT][QUOTE=Marco13]Ein Godwin Punkt für dich!!!111elf
Ich bin auch darüber gestolpert, als dieser Satz im anderen Thread auftauchte. Bin dann aber davon ausgegangen, dass das ironisch-„trollhaft“-„provokativ“ gemeint war.
Vielleicht auch nicht?[/QUOTE]
An welcher Stelle denn noch? Hab ich wat verpasst? Kann versehentlich sein. Ich glaube nicht dass das auf „wtf“ bezogen ist. Aber seltsam, eines Moderators „das zu lesen“. Wahrscheinlich ist jetzt mein Beitrag „deplatziert“.[/OT]
Cyborg: Kapier’ ich nicht. Ist wohl auch nicht wichtig.
[QUOTE=SlaterB]
wie steht es eigentlich mit Dingen wie StackTrace (StackOverflow!), Threads, GarbageCollector, Speichermanagement (OutOfMemory),
Sicherheit des Speichers vor Fremdzugriff, vor Bufferüberlauf usw.,
ist das alles unabhängig von einer ausführenden JVM, wäre das bei reinen Assembler-Programmen auch möglich
(natürlich bei entsprechenden Aufbau, aber Java anders geplant mit JVM? oder in der API hinterlegt?)
oder steht die interpretierende Ausführung mit Big Brother JVM drumherum für diese oder ähnliche Features?
müsste/ bietet ein Java-Prozessor in dieser Hinsicht weitaus mehr als ein normaler Prozessor,
von dem ich grob nicht mehr als paar Grundbefehle (ALU), prozessornahe Speicherpläze (Register) und sonst völlige Ignoranz zum Programm und Arbeitsspeicher in Erinnerung habe,
alles nur Speicheradressen und Bytes, der nächste Befehl mag sein was will, keinerlei Kontrolle/ Meinung/ Zustand
ein Thread-Wechsel ist doch eine komplizierte Folge von hunderten Befehlen, wo steht der Code dazu?[/QUOTE]
Interessante Fragen. Einerseits sind die JVM und die Java Language schon recht klar getrennt, aber spätestens DAS sind eben Berührungspunkte, wo Konzepte aus der einen Welt sich in der anderen wiederfinden. Eine genaue Abgrenzung der Verantwortlichkeiten ist (für mich) schwierig. Man könnte etwas händeweldend rechtfertigen: Die JVM ist als solche geplant und spezifiziert - also als etwas, was in einem größeren Kontext selbst wieder ausgeführt wird. Damit gibt es eine Stelle, wo z.B. Exceptions hin geworfen werden können. Bei einer echten Maschine würde sich die Frage stellen, wie sich dieses Verhalten (rein in Hardware) äußern sollte. Die einzige Analogie, die mir in den Sinn kam, waren “quiet NaN” gegenüber “signalling NaN” ( https://en.wikipedia.org/wiki/NaN ) - die sich aber letztlich auch nur in einem bit äußern, das von irgendjemandem abgefragt und interpretiert (…!?..) werden muss.
Z.B: Was passiert, wenn man in einem C+±Programm sowas macht wie
int* pointer = new int[3];
pointer[-42] = 666;
? In der Praxis überschreibt man da eben irgendwelchen Speicher, oder das Betriebssystem (die “Ausführungsumgebung”) faselt was von “Segmentation Fault”. Das ist aber nichts, was z.B. in der Spec der x86-Prozessoren enthalten ist. Und in der C+±Sprachspec steht da vermutlich (!) bestenfalls sowas wie “undefined behavior”. (Wenn man die Worte “undefined behavior” mit “UB” abkürzen würde, wären die C+±Spacs vermutlich nur halb so lang, wie sie jetzt sind :rolleyes: ). WO tatsächlich ein (sinngemäßer) Satz steht, der klipp und klar sagt: “Wenn auf Speicher zugegriffen wird, der ~irgendwas wie: nicht dem gleichen Prozess zugeordnet ist, dann passiert dies-und-das”, weiß aber auch ich nicht.
Worauf ich mit meinen etwas philosophischen Einlässen oben eigentlich rauswollte: Irgendwann hat man sowas wie
0x10 0xB1 0x34
0xC0 0x21
0x11 0xA4
und ob das nun die Bytewerte (Opcodes) von Java Bytecode sind, oder Opcodes aus dem x86-Befehlssatz, weiß man nicht. Es gibt einen Prozessor, der auf Basis dieser Abfolge “irgendwas macht”. Und wie cmrudolph schon angedeutet hat: Man könnte viel vom Java-Bytecode praktisch 1:1 in x86-Code übersetzen. Den größten Gehirnknoten würde da die Tatsache verursachen, dass x86 eben registerbasiert ist, und die JVM ist stackbasiert. Aber sowas wie
oberstesStackElement = iadd
oberstesStackElement, zweitesSackElement
vs.
add
erstesUndZielRegister, zweitesRegister
ist schon recht offensichtlich.
Weshalb auch, im Endeffekt heisst das nur es ist nicht näher spezifiert. Das ist in dem Sinne auch vernünftig schließlich gibt es C/C++ Interpreter und alle möglichen Systeme die sicher auch von dem gängigen Wald-/Wiesendesktopsystem architekturell abweichen und für die willst du nicht alles beschreiben.
[OT][QUOTE=Marco13]Cyborg: Kapier’ ich nicht. Ist wohl auch nicht wichtig.[/QUOTE]
Ich wollte nur wissen, an welcher anderen Stelle im Forum das geschrieben wurde, und von wem, wenn überhaupt … wie es überhaupt „rechtlich“ damit aussieht, hab ich keinen blassen Schimmer von. Kann sein selbstverständlich, eine Wissenlücke.
Da es doch arg Offtopic in Allgemeine Themen — kann/sollte meine 2 Beiträge weg, wenn „deplatziert“.
Dann bin ich halt der Sündenbock. :D[/OT]
Nun, irgendwo muss (oder sollte) das schon beschrieben sein. „Natürlich“ nicht in der Prozessor-Spec, und „natürlich“ nicht in der Sprach-Spec (schließlich weiß die Sprache nicht, ob ihr Compilat auf einem Windows-Desktop oder dem Embdedded Controller einer intelligenten Kaffeemaschine laufen wird. Aber ich würde schon hoffen, dass irgendwo in den Tiefen irgendeines Microsoft/Windows-Dokuments das genaue Verhalten für dieses System beschrieben ist - genauso wie es eben für die JVM gemacht ist. (Nebenbei: Wie die „umgebende“ Anwendung (die die JVM ausführt) auf solche Fehler reagiert, bleibt so gesehen ja auch ihr überlassen…)
Nach dem sich aus meiner Bemerkung und anfänglichen Sichtweise hier doch eine Nette “Diskusion” (im Sinne von: verschiedene Sichtweisen) ergeben hat, “vervollständige” ich mal mein ursprüngliches Statement:
[…] wenn man mit einer Interpreter-Sprache (aus Sicht eines auf einer x86-Architektur laufendem OS) arbeit […]
Mal ehrlich jetzt? Ihr unterhaltet euch darüber, ob Java eine Interpretersprache ist, oder nicht? Also sicher ist schon mal, dass der Bytecode erstmal interpretiert werden muss. Ich weiß zwar nicht, ob das noch aktuell ist, aber zumindest konnte man, seitdem Java standardmäßig mit dem JIT-Kompiler ausgeführt wird, die JVM auch im Interpretermodus starten. Der Bytcode wird dann während der Ausführung nicht mehr in Maschinencode umgewandelt und auch nicht mehr optimiert.
Kurzgesagt: Seit JIT ist Java sicher keine reine Interpretersprache mehr.