You seem confused about what a linker does. It does not produce machine code. It merely sticks together (links, if you will) pieces of machine code that have already been produced by a compiler (typically).
What you were probably thinking of is that a linker produces an executable, or at least that's what a linker like ld
does. This was the point of ld
: to take pre-compiled libraries (.a
files in UNIX parlance) and combine them together with object files to produce executables so you wouldn't need to recompile a library for every program that used it.
That said, there's nothing that keeps a compiler from just outputting an executable directly, but I don't think that this is actually happening that commonly. I'm pretty sure most languages that compile to native code do still have a linking stage. They just don't require you to explicitly call it yourself. In fact, LLVM is a popular backend for modern languages targeting native code, and building a new linker is one of the projects of LLVM. The premise that modern languages, at least those that directly produce native code, don't have a linking stage is incorrect.
For languages that primarily target a VM, they may not use ld
, but that doesn't mean they don't have linkers. The recent addition to Java of "modules" has lead to jlink
. More fundamentally and historically, the most natural thing to call a linker in Java is the ClassLoader. It even mentions linking the class. This is a dynamic linker. It performs the link stage at runtime. Here's the description of linking from the Java Language Specification. Of course, as always, there's nothing that stops you from compiling Java to a native executable. In that vein, there's also nothing stopping Java bytecode from being machine code.