JIT in the .Net will compile the IL to native code, i.e., machine code. So at the end, the machine code will be executed. The native code is kept in memory and will be lost if you shut down the machine. Next time you start the machine and run the code again, it will be re-compiled. Of course, you can always pre-compile the IL code into native code. Actually, there are three types of JITers:
Econo-JIT
Quickly generates fairly low quality native code (fast to generate, almost
no optimization) - caches generated code in memory - throws out generated
code to make room for new code as needed - may result in recompilation of
the same function
Regular JIT
Generates more optimized native code than the econo-JIT - currently keeps
code in memory for the life of the app domain - may cache and discard code
like the econoJIT in later versions of the runtime
PreJIT
Saves JITted code to disk so application doesn't have to re-compile when
loaded - can also take a little longer to optimize and generate more
optimized native code