The JVM (Java Virtual Machine) has an instruction set just like a real machine. The name given to this instruction set is Java Bytecode. It is described in the Java Virtual Machine Specification. Other languages are translated into a bytecode before execution, for example ruby and python. Java's bytecode is at a fairly low level while python's is much more high level.
Interpretation and JIT compilation are two different strategies for executing bytecode. Interpretation processes bytecodes one at a time making the changes to the virtual machine state that are encoded in each instruction. JIT compilation translates the bytecode into instructions native to the host platform that carry out equivalent operations.
Interpretation is generally quick to start but slow during execution, while JIT has more startup overhead but runs quicker afterwards. Modern JVMs use a combination of interpretation and JIT techniques to get the benefit of both. The bytecode is first interpreted while the JIT is translating it in the background. Once the JIT compilation is complete, the JVM switches to using that code instead of the interpreter. Sometimes JIT compilation can produce better results than the ahead-of-time compilation used for C and C++ because it is more dynamic. The JVM can keep track of how often code is called and what the typical paths through the code are and use this information to generate more efficient code while the program is running. The JVM can switch to this new code just like when it initially switches from the interpreter to the JIT code.
Just like there are other languages that compile to native code, like C, C++, Fortran; there are compilers for other languages that output JVM bytecode. One example is the scala language. I believe that groovy and jruby can also convert to java bytecode.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…