All syntax errors and some of the semantic errors (the static semantic errors) are detected by the compiler, which generates a message indicating the type of error and the position in the Java source file where the error occurred (notice that the actual error could have occurred before the position signaled by the compiler).
Other semantic errors (the dynamic semantic errors) and the logical errors cannot be detected by the compiler, and hence they are detected only when the program is executed.
Let us see some examples of errors detected at runtime:
Example 1: Division by zero:
int a, b, x; a = 10; b = Integer.parseInt(kb.readLine()); x = a / b; //ERROR if b = 0
This error occurs only for a certain configuration of the input (b = 0).
Example 2: File does not exist:
FileReader f = new FileReader("pippo.txt");
The error occurs only if the file pippo.txt does not exist on the harddisk.
Example 3: Dereferencing of a null reference:
String s, t; s = null; t = s.concat("a");
The concat() method cannot be applied to a reference whose value is null. Note that the above code is syntactically correct, since the concat() method is correctly applied to a reference of type String, but it contains a dynamic semantic error due the fact that a method cannot be applied to a reference whose value is null.