JDK 21 and JDK 25 removed or refuse to run several Java APIs and features, including the Security Manager, sun.misc.Unsafe, Applet, Thread.stop and some javax imports. This check scans an open Java file or the workspace, identifies each blocker on its line, names the JEP that removed it and gives a replacement call. It runs in your browser.
Finds Java code that JDK 21/25 removed or refuses to run — Security Manager, sun.misc.Unsafe, javax.* imports, Applet, Thread.stop — before you leave Java 17. Runs entirely in your browser — nothing is uploaded.
Same engine as the VS Code extension, byte for byte.
Free for the file open in your editor - no key, no limit. The workspace sweep and the report ask for a key.
Open VSX (Cursor, VSCodium)npmMCP server (npx)Docker Hubnpx @readystack/jdk25-upgrade-blocker-lint <file> npx @readystack/jdk25-upgrade-blocker-lint --mcp docker run --rm -v "$PWD:/w" getreadystack/jdk25-upgrade-blocker-lint /w
Team? One key for every ReadyStack linter, 5 seats, $149 once
Sweeps the whole workspace and writes the dated migration report file — every file, blocker, JEP and replacement.
One payment, one licence key for this tool. The key is shown right after payment.
A Java migration consultant bills $120-$200 an hour; a two-day audit of one repo is over $2,000.
Buy the full version — $29· ReadyStack
Real numbers from this tool, line by line.

Twenty-three blockers sat in one 64-line Java file — the kind of invoice exporter a Spring Boot team in Frankfurt or Austin still has in production, and the kind an AI assistant writes when most of its Java was written for Java 8.
Fifteen of the twenty-three were errors: calls that JDK 21 or JDK 25 has removed, disabled, or will refuse to run. Eight were warnings with a one-line replacement. The file compiles cleanly on Java 17 today.
That is the whole problem. javac treats "deprecated for removal" as a warning, prints it, and writes a perfectly good class file. Your pipeline stays green. The failure does not disappear — it moves to run time, on the new JDK, after the upgrade ticket is closed.
System.setSecurityManager(new SecurityManager()) throws UnsupportedOperationException on JDK 24 and later. JEP 486 permanently disabled the Security Manager, and the .policy file next to it now grants nothing at all. AccessController.doPrivileged is worse, because it does not throw: it still compiles, still returns your value, and simply stops elevating anything.
import javax.persistence.Entity; is the quiet one. It compiles against a Jakarta EE 10 runtime — Spring Boot 3, Quarkus 3, Payara 6, WildFly 27 and up. The runtime scans jakarta.*. Your entity is never registered, the table is never mapped, and nothing anywhere says so.
extends Applet is the loud one. The Applet API was removed outright in JDK 25 (JEP 504), so the build stops, usually in a file nobody has opened in nine years.
Unsafe.getUnsafe().allocateMemory(64L) is on a published path out: the memory-access methods are deprecated for removal under JEP 471, and JDK 24 warns on them by default under JEP 498. Arena.ofConfined().allocate(64L) is the replacement.
workerThread.stop() has thrown UnsupportedOperationException since JDK 20. protected void finalize() is deprecated for removal under JEP 421, and once finalization is disabled the cleanup you wrote simply never runs.
This is not only a problem in old code. An assistant trained largely on Java 8 and Java 11 will write javax.servlet imports, new Integer(3), new Locale("de", "DE") and Class.forName(...).newInstance() into the service you are migrating this week.
JDK 25 Upgrade Blocker Lint reads .java files and names each of these on its own line: the JEP that removed it, and the call that replaces it. Eighteen rules. Comments are stripped before matching, so a JEP number quoted in a javadoc is not a finding.
The bundled fixtures are the measurement, not a claim: _fixtures/dirty.java returns 23 findings, 15 errors and 8 warnings, and every one of the 18 rules fires at least once. _fixtures/clean.java is the same class with each fix applied, and returns 0.
The free tier is the reading job, finished: all 18 rules on the file you have open, with no key and no cap, for as long as you use it. The paid tier is a different job — the workspace sweep that reads every .java file in the repository and writes one dated migration report listing each file, blocker, JEP and replacement, for the upgrade ticket and for the people who were not sitting in the editor. That sweep is $29 once, with commercial and CI-seat use. A Java migration consultant bills $120 to $200 an hour to read the same files, and a two-day audit of one repository runs past $2,000.
Oracle premier support for Java 17 ends in September 2026. The upgrade is already on someone's calendar; the question is only whether the removed calls are found in the editor or in production.
It reads your .java files and flags the calls JDK 21 and JDK 25 removed, disabled or refuse to run: Security Manager, AccessController.doPrivileged, sun.misc.Unsafe, javax.* Jakarta imports, the Applet API, Thread.stop, finalize and more. 18 rules; the bundled 64-line fixture returns 23 findings, 15 errors and 8 warnings, each with its line, its JEP and the replacement call.
Java teams moving a Spring Boot 2 or Jakarta EE service off Java 17 onto JDK 21 or the JDK 25 LTS, and the platform engineer who owns that upgrade ticket. If your repository still compiles on 17 but nobody has read every file for removed APIs, this reads them in one pass.
javac prints a deprecation warning and then produces a working class file, so the build stays green and the UnsupportedOperationException arrives in production instead. AI assistants trained on older Java keep emitting javax.persistence imports and setSecurityManager calls, so the problem reappears in code written this week.
Free, forever: the file you have open, all 18 rules, no key and no cap — that reading job finishes on its own. The key covers the other job: sweeping every .java file in the workspace and writing one dated migration report file with every blocker, JEP and replacement. That sweep is $29 once.
A Java migration consultant bills $120 to $200 an hour, and a two-day audit of a single repository runs past $2,000. Reading one service by hand takes an afternoon and misses the quiet ones, because a javax.servlet import looks correct until the Jakarta runtime silently skips the bean.
A general AI chat answers from training data with a cutoff date, cannot read your repository and names no rule version. JDK 25 Upgrade Blocker Lint checks the file you open against 18 rules from a rule set dated 2026-09-20, and points at the exact line. For a filing, an audit or a client you need that dated result on your own files.
One question, answered by the person who built it. Your email only if you want the answer sent.
Paste this code into your page. It runs in your visitor’s browser and stays up to date. Nothing your visitors type is stored.
For businesses: your name and logo instead of ours, and each visitor’s result + e-mail in your inbox (only when they tick consent) — Pro from $19/month. See Pro →