Short answer
Start with top (or top -H -p <pid> to see per-thread CPU) and note the hottest native thread ids, converting them to hex.
Explanation
Take a thread dump with jstack <pid> or kill -3, find the thread whose nid matches that hex id, and read its stack to see the hot loop. Correlate with jstat -gc <pid> 1000 to rule out GC thrashing (a climbing FGC count means full GCs are burning the CPU, pointing at heap pressure or a leak rather than application code). The discipline is mapping an OS-level hot thread back to a specific Java stack frame instead of guessing.
Common mistakes
- Restarting the service before collecting evidence.
- Not mapping the hot thread id (top -H) to a thread dump.