#1139926 plm: Java exercises fail on JDK 21+ (Thread.stop) -- runtime compilation aborts

Package:
plm
Source:
plm
Submitter:
Juan M. Méndez Rey
Date:
2026-06-13 17:51:02 UTC
Severity:
normal
#1139926#5
Date:
2026-06-13 15:18:38 UTC
From:
To:
Dear Maintainer,

On a current Debian system (default-jdk is now OpenJDK 26), running a *Java*
exercise in PLM fails: the embedded compilation aborts and the exercise cannot
run. The Scala, Python and C language modes are unaffected; this is specific to
the Java mode.

Root cause
----------
What I gathered investigatig this: for a Java exercise, PLM recompiles a set of
its own framework sources together
with the student code, in-process, via javax.tools.JavaCompiler
(plm.core.lang.LangJava / CompilerJava). One of those framework sources,
src/plm/core/model/LessonRunner.java, calls the deprecated-for-removal
java.lang.Thread.stop():

/** Stop all the threads that were already started. Harmful but who cares? */
@SuppressWarnings("deprecation")
public void stopAll() {
while (runners.size()>0) {
Thread t = runners.remove(runners.size() - 1);
t.stop(); // harmful but who cares ?
}
}

On the JDK shipped in current Debian this recompilation fails, e.g.:

/usr/share/java/plm.jar(/plm/core/model/LessonRunner.java):110: cannot find
symbol
symbol: method stop()
location: variable t of type java.lang.Thread

(Two further framework sources only emit deprecation-for-removal warnings, not
yet fatal, but should be modernized at the same time:
- src/plm/universe/World.java -- java.lang.ThreadDeath
- src/plm/core/lang/LangJava.java -- java.security.AccessController)

Thread.stop(), Thread.suspend()/resume(), ThreadDeath and AccessController are
all deprecated for removal; relying on them in code that is recompiled at run
time is fragile across JDKs and will only get worse.

To reproduce:
1. Install plm on a system whose default-jdk is OpenJDK 21 or newer.
2. Launch plm, open any Java exercise, type e.g. System.out.println("hi");
3. Run it -> the exercise aborts with the compilation error above.

The proposed fix:

Stop using Thread.stop(). The straightforward replacement is cooperative
cancellation via Thread.interrupt() in stopAll().
Caveat: interrupt() is cooperative, so a student program
stuck in a tight non-cooperative loop would not be force-killed the way Thread.stop() did.
Another robust solution would run the student code in a separate JVM/process that can be hard-killed.

I believe that the cooperative approach is the modern practice and
restores Java exercises on current JDKs.

I will forward a proposed patch upstream (https://github.com/oster/PLM) and
attach/track it here.

Thanks,
Juan

#1139926#10
Date:
2026-06-13 17:50:00 UTC
From:
To:
cooperative Thread.interrupt(), so PLM's in-process recompilation of its
framework sources no longer fails and Java exercises run again.

Forwarded upstream: https://github.com/BuggleInc/PLM/pull/528

This is independent of the (separate, gated) Scala 2.12 migration, so I plan to
upload it as a standalone NMU together with the fix for #1139932, rather than
hold it behind the Scala work.