Note: this answer is on a "per-run" context. The code is normally JITted each time you run the program. Using ngen or .NET Native changes that story, too...
Unlike HotSpot, the CLR JIT always compiles exactly once per run. It never interprets, and it never recompiles with heavier optimisation than before based on actual usage.
This may change, of course, but it's been that way since v1 and I don't expect it to change any time soon.
The advantage is that it makes the JIT a lot simpler - there's no need to consider "old" code which is already running, undo optimisations based on premises which are no longer valid etc.
One point in .NET's favour is that most CLR languages make methods non-virtual by default, which means a lot more inlining can be done. HotSpot can inline a method until it's first overridden at which point it undoes the optimisation (or does some clever stuff in some cases to conditionally still use the inlined code, based on actual type). With fewer virtual methods to worry about, .NET can largely ignore the pain of not being able to inline anything virtual.
EDIT: The above describes the desktop framework. The Compact Framework throws out native code when it wants to, JITting again as necessary. However, this still isn't like HotSpots adaptive optimisation.
The micro framework doesn't JIT at all apparently, interpreting the code instead. This makes sense for very constrained devices. (I can't say I know much about the micro framework.)
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…