Why Java is both compiled and interpreted language when the JIT also compiles the bytecode?

There is a bit of misunderstanding here.

In normal circumstances java compiler(javac) compiles java code to bytecodes and java interpreter(java) interpretes these bytecodes(line by line), convert it into machine language and execute.

JIT(Just in time) compiler is a bit different concept. JVM maintains a count of times a function is executed. If it exceeds the limit then JIT comes into picture. java code is directly compiled into machine language and there on this is used to execute that function.


Java is a programming language.

It has a specification (the JLS) that defines how Java programs should act.

As a language itself, it does not specify how it should be executed on different platforms. The way it runs, with a JIT or without a JIT is entirely implementation based.

  • If I write a Java runtime tomorrow that does not do JIT compilation at all I can call Java interpreted.

  • If I take a Java machine (and people seriously made those) that uses Java bytecode as assembly, I can call Java strictly compiled.

A lot of other languages do this:

  • Is python an interpreted language? (CPython) or is it JITed (PyPy)?
  • Is Lua interpreted (old lua interpreters) or is it compiled (LuaJIT)?
  • Is JavaScript interpreted (IE6 style) or is it compiled (v8)?

For the sake of precision, let's make clear this is not a Java programming language question, but a JVM feature.

In JVM first implementations, JIT didn't exist and bytecode was always interpreted. This was due to a design decision to make compiled code independent of the physical machine and OS running java, and is still valid today.

As a later refination, JIT was introduced in the JVM implementation for a faster execution, but the bytecode must still be valid and pass all the validations before being translated to binary. This way you keep the platform independence, all the sanity and security checks and you gain performance.