I believe there are some differences between what .NET does and what mainstream Java does. For instance, objects can be stack allocated even if they can't be turned into collections of scalars. This allows the JIT to stack allocate small known-sized arrays.
Linq contains a goodly number of hand-crafted special-case enumerators for common collections, or collections with certain interfaces, or span projections that are really nice optimizations but can complicate things for the JIT.
We are a small tight-knit team, happy to both teach and learn new ways of making code run faster.
If you're curious about the kind of work we have been doing recently, check out the JIT section of https://devblogs.microsoft.com/dotnet/performance-improvemen... and or https://github.com/dotnet/runtime/blob/main/docs/design/core...