Skip to content

Run on modern JDKs and jgit: Thread.stop, commit signing, console noise#528

Merged
mquinson merged 2 commits into
BuggleInc:javaUIfrom
vejeta:modern-jdk-jgit
Jun 15, 2026
Merged

Run on modern JDKs and jgit: Thread.stop, commit signing, console noise#528
mquinson merged 2 commits into
BuggleInc:javaUIfrom
vejeta:modern-jdk-jgit

Conversation

@vejeta

@vejeta vejeta commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

These three independent fixes make PLM usable again on a current system
(tested on Debian with OpenJDK 26 and jgit 6.7).

Description of the problems

  1. Java exercises no longer run (Thread.stop). When running a Java exercise PLM
    recompiles a set of its own framework sources in process, together with the
    student code. LessonRunner.stopAll() called Thread.stop(), which is
    deprecated for removal; on recent JDKs that recompilation fails with
    "cannot find symbol: method stop()", so no Java exercise can run. Replaced
    with cooperative Thread.interrupt().
    Caveat: interrupt() is cooperative, so a student program stuck in a tight
    non-cooperative loop is no longer force-killed the way Thread.stop() did.
    A fully robust solution would run the student code in a separate,
    hard-killable JVM; that is left as a follow-up.

  2. Progress-tracking commits fail when commit.gpgsign is enabled. GitSpy /
    GitUtils create a commit on every run. If the user's git configuration
    enables commit signing (common on developer machines), jgit throws
    "ServiceUnavailableException: Signing service is not available" and prints a
    stack trace to the console on every run, in every language. PLM's internal
    bookkeeping commits must never be signed: setSign(false) on each
    CommitCommand.

  3. Framework compilation warnings leak into the student console. The in-process
    recompilation of PLM's own framework sources emits deprecation/unchecked
    warnings (e.g. ThreadDeath and AccessController being deprecated for removal,
    raw-type usage) into the in-application console -- noise the student did not
    write and cannot act on. Show only Diagnostic.Kind.ERROR in LoggerPanel;
    real errors in the student's code are still shown.

Solutions applied

LessonRunner.stopAll(): Thread.stop() (deprecated for removal) made PLM's in-process recompilation of its framework sources fail on recent JDKs, so no Java exercise could run; use cooperative Thread.interrupt() instead.

GitUtils: when the user's git config enables commit.gpgsign, jgit failed to sign PLM's internal tracking commits (ServiceUnavailableException) and dumped a stack trace to the console on every run; setSign(false) on them.

LoggerPanel: show only compilation errors, not the deprecation/unchecked warnings from PLM's own framework sources, which are noise to the student.

Follow-up (not in this PR):

the framework still references ThreadDeath and
java.security.AccessController, both deprecated for removal. They should be
modernized (cooperative-cancellation handler; drop the no-op doPrivileged) so
PLM keeps compiling when a future JDK removes them.

vejeta added 2 commits June 13, 2026 18:22
LessonRunner.stopAll(): Thread.stop() (deprecated for removal) made PLM's
in-process recompilation of its framework sources fail on recent JDKs, so no
Java exercise could run; use cooperative Thread.interrupt() instead.

GitUtils: when the user's git config enables commit.gpgsign, jgit failed to
sign PLM's internal tracking commits (ServiceUnavailableException) and dumped a
stack trace to the console on every run; setSign(false) on them.

LoggerPanel: show only compilation errors, not the deprecation/unchecked
warnings from PLM's own framework sources, which are noise to the student.
The custom JavaFileManager.list() returned every in-process compiled class for
any CLASS_PATH package query. javac trusts that list(package=P) returns classes
of P and derives their binary name as P + the file's simple name, so a class
such as plm.core.model.session.SourceFile leaked into the query for
scala.reflect.internal.util and was read as scala.reflect.internal.util.SourceFile
("class file contains wrong class"), breaking any exercise whose recompiled set
holds two classes with the same simple name (e.g. a Buggle Java exercise). Filter
the compiled classes by the queried package, like the source loop just above.
@mquinson

Copy link
Copy Markdown
Member

Thanks a lot, it's in!

@mquinson mquinson merged commit 43788e9 into BuggleInc:javaUI Jun 15, 2026
0 of 3 checks passed
@vejeta

vejeta commented Jun 15, 2026

Copy link
Copy Markdown
Contributor Author

Thanks @mquinson,

Thanks for merging this!

I discovered this while preparing the next scala 2.12 packages for Debian.

Since you also maintain PLM in Debian: these four fixes are queued there too,
as a backport in the PLM packaging update that ports it to Scala 2.12, so PLM
keeps working on a current Debian (OpenJDK 26):

https://salsa.debian.org/java-team/plm/-/merge_requests/4

That PLM update is waiting on Scala 2.12 returning to the archive (the bootstrap effort), tracked here:
https://salsa.debian.org/java-team/scala/-/merge_requests/2

I will keep you posted to coordinate the Debian upload whenever it suits you.
Thanks again!

PS: I loved discovering this package and being brought up to date, I may introduce it to my nephews/nieces

@mquinson

Copy link
Copy Markdown
Member

Thanks for your patch and your support, @vejeta ;)

I will upload a new upstream release with these fixes to Debian. I just need to update my github action to get the tests to pass again. PLM definitely needs more love, in many regards.
The tests are so outdated that your changes do not pass because it's tested against jgit v3.2.0 released back in 2013...
I am about updating the dependencies that are manually added to the git and linked from the build.xml but that's clearly not the right approach. I would appreciate if you could advise a better way. For example, we could try to build on a Debian image using the system-wide libraries. That would ensure that I see the deprecation warnings in the logs and get a chance to fix them, but I'm unsure of how to build a self-contained jarfile this way. I need such a bloated jarfile for non-Debian users.
If you have the time to advise for a solution, that would be really appreciated, and I'll implement this if you don't have the time for that. The hint is very welcomed as I kinda left the Java ecosystem 10 years ago.
Thanks,

@vejeta

vejeta commented Jun 15, 2026

Copy link
Copy Markdown
Contributor Author

@mquinson, glad to help!

I went ahead and prepared a possible solution in #529

The easiest thing is to move to a Maven build: dependencies are declared and fetched
(no more vendored lib/ jars), including a current jgit so the deprecations now surface in
the build, and maven-shade-plugin produces the same self-contained jar for
non-Debian users (mvn package).

The fat jar and the Debian build then come from the one pom.xml:
Debian builds it offline against the system libraries via
maven-debian-helper, with no bundling, and we can take care of that
in the Debian side.

Let me know what you think.

Cheers!
Juan

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants