This is called bootstrapping .
Compilers
Languages are just specifications . Although related, languages and compilers are different things .
Compilers and libraries form what the specification says . It is obvious that the first implementation of the language must be written in another language. You can then use the language itself to create a new implementation written on it.
Compilers are relatively basic algorithms, full of specific complexities, of course. Enter text data, process, and there's the complexity, and it generates a data, possibly binary that a virtual or physical machine knows how to execute. It is only a transformation algorithm to follow specific rules. So they generate a program that can be run and this can be a compiler, a virtual machine, an operating system, anything.
I even understand the curiosity, but I find it strange that it seems something very difficult to achieve. I think the only "secret" is to know that the first compiler should be done in another language.
Actually some languages are made incrementally. It makes a compiler that treats the minimum, and adds functionality later. So you almost have an initial compiler in the language itself. Of course the first interactions of this language development will be slightly different from the one desired at the end, and somewhat limited.
Programming languages can produce anything , so it's no secret that a language produces a compiler for itself , provided there is a first implementation.
Of course, some languages are not the right ones to produce compilers.
The best implementations of Java are actually written in C ++. Java today does not seem very suitable for producing compilers. It was already worse. Java is compiled and not interpreted in its database. It is possible to have an interpreter.
Interpreters
An interpreter is nothing more than a compiler that in the end instead of generating an executable, it already executes what has been analyzed. An interpreter is an executable program like any other. But in this case the compiler generates a bytecode and it will be "interpreted" by the virtual machine
Of course, in case the interpreter runs itself it needs to be reentrant .
What I can guarantee is that it has a code snippet in another language, a snippet that just does the bootstrap of the virtual machine. Reading the article on Wikipedia, talk about it:
A small C loader is responsible for loading the boot image at runtime
The compiler, from the interpreter, is separate from the virtual machine, even if it is in the same executable. The virtual machine does not interpret Java, it interprets a bytecode , and by that I understood this Jikes nor uses the bytecode .
Obviously I do not have details of this project and I can not state every detail of how it works.
More information
C and e C ++ compilers have been written in C ++ for quite some time. Some still have a good deal written in C. Someone can do it in Assembly (not Assembler), but for years no one seriously does that.
C # today has its compiler written in C # and works better than the original written in C ++. The runtime is basically written in C ++.
I've already talked about this in The First Programming Language .