Syntaxfehler, Laufzeitfehler, Compiletime, Runtime, Compiler und Interpreter
Compiler und Interpreter
Grundsätzlich unterscheidet man zwischen kompilierten und interpretierten Programmiersprachen. Die interpretierten Programmiersprachen nennt man häufig auch Skriptsprachen. Kompilierte Programmiersprachen benötigen einen Compiler, interpretierte Programmiersprachen benötigen einen Interpreter.
Compiler und Interpreter sind selbst auch wieder Programme.
Kompilierte Sprachen
Einen Compiler kann man sich dabei vorstellen wie einen Übersetzer, der ein Buch aus einer Sprache in eine andere übersetzt. Deutscher Schriftsteller, französischer Leser. Der Übersetzer übersetzt das deutsche Buch ins Französische, der französische Leser kann es zu einem anderen Zeitpunkt problemlos lesen.
Bei kompilierten Programmiersprachen ist das Prinzip ähnlich. Der Compiler übersetzt den menschenlesbaren Code in maschinenlesbaren Code. Den Zeitpunkt, an dem der Code übersetzt wird, nennt man Compiletime (Compile-Zeit), der Zeitpunkt, an dem der Code von der Maschine ausgeführt wird, nennt man Runtime (Laufzeit).

Diese beiden Zeitpunkte unterscheiden sich in der Regel erheblich. Genau wie bei der Übersetzung des Buches.
Das geschieht auch deutlich früher als das Lesen der übersetzten Ausgabe.
Vorteile von kompilierten Sprachen sind ihre Schnelligkeit und die Passgenauigkeit auf die Maschine, auf der der Code ausgeführt wird. Der zweite Punkt ist allerdings aus einer anderen Perspektive eher wieder ein Nachteil, da der Code dadurch nicht mehr Plattformunabhängig ist und für Windows, Linux, MacOS, etc. unterschiedlicher Code geschrieben werden muss.
Beispiele für kompilierte Sprachen sind z.B. C oder C++
Interpretierte Sprachen
Interpretierte Sprachen funktionieren eher wie Simultanübersetzer z.B. bei internationalen Konferenzen. Während der Vortragende z.B. in Deutsch spricht, übersetzt der Übersetzer, on the fly, die Rede ins Französische. Genauso macht es der Interpreter der Skriptsprache. Zeile für Zeile wird der menschenlesbare Code, während der Ausführung, in eine maschinenlesbare Form gebracht. Hier gibt es also keine Unterscheidung zwischen Compilezeit und Laufzeit.

Der Nachteil von interpretierten Sprachen ist, dass die Ausführung in der Regel etwas länger dauert, da eben immer erstmal wieder übersetzt werden muss.
Vorteile von interpretierten Sprachen sind, dass sie in der Regel plattformunabhängig sind und dass sie nicht kompiliert werden müssen. Dadurch können Programme schneller entwickelt werden. (Es lässt sich allerdings durchaus darüber diskutieren ob das wirklich stimmt, da bei interpretierten Programmen kein Compiler da ist der bei der Fehlersuche hilft.)
Beispiele für Skriptsprachen sind z.B. PHP oder Ruby
Java ByteCode
Bei Java hat man versucht die Vorteile aus beiden Welten zu kombinieren. Böse Zungen behaupten allerdings, dass man eher die Nachteile aus beiden Welten kombiniert hätte.
Man könnte das evtl. mit einem Text vergleichen der z.B. mit Google Translate aus dem Deutschen ins Französische übersetzt wird. Er ist also in einer halbwegs verständlichen Form und ich muss ihn während des Lesens noch Zeile für Zeile simultan in eine sprachlich wirklich richtige Form übersetzen (zugegeben, der Vergleich hinkt etwas).
Der Java Compiler (javac) übersetzt also zur Compiletime den menschenlesbaren Java Code in leichter interpretierbaren, sogenannten ByteCode. Dieser wird dann von der sogenannten Java Runtime zur Laufzeit interpretiert. Wir haben also auch hier einen zeitlichen Unterschied zwischen Runtime und Compiletime.

Fehler können prinzipiell zur Compiletime und zur Runtime auftreten.
Fehler, die zur Compiletime auftreten, sind in der Regel sogenannte Syntaxfehler.
Diese Art von Fehlern wird vom Compiler gefunden und bemängelt.
Laufzeitfehler sind Fehler, die auftreten, während das Programm ausgeführt wird.
Sprich: Der Compiler hat diese Fehler nicht gefunden.