JIT compilation is risky because of the W^X violation: at runtime, it is possible to generate new code, similar to an eval() in dynamic languages. But being able to dynamically generate executable machine code is not only essential to many high-performance runtimes including OpenJDK, .NET Runtime, and V8 – it's also super useful for malware.
However, such a risk doesn't mean a JIT compiler is inherently insecure. The important insight is that just because a JIT compiler can produce native code doesn't mean that this code can now do anything. The JIT compiler can introduce restrictions of its own (e.g. ensuring memory safety), and the code is still limited by the security models of the CPU and the operating system. Thus, JIT compilation is at the heart of many highly secure sandboxes such as V8 or BPF.
Also, not every W^X violation is equal. In a security-conscious program, all memory pages are either writeable or executable at any given time, but not both at the same time. A user-space JIT compiler will need to issue syscalls such as mprotect() to change the flags on a page, and these syscalls can be audited and possibly denied. A malware would either need to exploit a bug that introduces a page that is both writeable and executable, or would have to inject code into a writeable page that will later become executable. If the JIT compiler is written carefully – and the mentioned runtimes are incredibly robust and well-tested – such exploitable vulnerabilities will be quite rare.
There is definitely a tradeoff between security and performance. However, a security-conscious JIT compiler will not lead to a large loss of security. JIT can however lead to a large gain of performance. In my experience, interpreters are often 10× to 100× slower than native code, but this is highly dependent on the use case and on the granularity of the interpreter.
It is correct that JIT compilation makes static analysis on the level of machine code less useful. This might be unacceptable in some settings, for example in a certain app store that wants to review all the code. However, static analysis is inherently limited and often not suitable to provide strong security guarantees. Runtime checks that allowlist permissible operations and deny anything else are much more suitable to limit the behaviour of real-world programs. For example, a browser might sandbox untrusted code in a separate process in which JIT is allowed, but no interaction with the outside world except by sending messages to a supervisor process (e.g. enforcible by seccomp on Linux). Even if the sandbox runs malware, it will not be able to do anything that ordinary non-JIT code wasn't already able to do.