Skip to content

FELIX-6759 - Java 25 LTS support - #433

Open
paulrutter wants to merge 27 commits into
masterfrom
feature/FELIX-6759-Java-25-LTS
Open

FELIX-6759 - Java 25 LTS support#433
paulrutter wants to merge 27 commits into
masterfrom
feature/FELIX-6759-Java-25-LTS

Conversation

@paulrutter

Copy link
Copy Markdown
Contributor

Try-out building framework and HTTP subprojects against java 25 to see what will break

- Try-out building framework and HTTP subprojects against java 25 to see what will break
@paulrutter paulrutter changed the title FELIX-6759-Java-25-LTS FELIX-6759 - Java 25 LTS support Jul 14, 2025
- Use 25-ea (Early access)
- Update mockito-core to a version that has jdk 25 support via byte-buddy
- Update awaitility
- Disable jetty bundle
- Don't rely on snapshot build for jetty
@stbischof

Copy link
Copy Markdown
Contributor

can you also do a change in scr to trigger this test

@stbischof

stbischof commented Jul 14, 2025

Copy link
Copy Markdown
Contributor
2025-07-14T15:00:46.1938964Z [�[1;34mINFO�[m] Results:
2025-07-14T15:00:46.1939060Z [�[1;34mINFO�[m] 
2025-07-14T15:00:46.1939191Z [�[1;31mERROR�[m] �[1;31mErrors: �[m
2025-07-14T15:00:46.1939647Z [�[1;31mERROR�[m] �[1;31m  JakartaSpecificWebsocketIT.testWebSocketConversation » NumberFormat For input string: "25-beta"�[m
2025-07-14T15:00:46.1940070Z [�[1;31mERROR�[m] �[1;31m  JettySpecificWebsocketIT.testWebSocketConversation » NumberFormat For input string: "25-beta"�[m
2025-07-14T15:00:46.1940535Z [�[1;31mERROR�[m] �[1;31m  JettySpecificWebsocketIT.testWebSocketServletHttpService » NumberFormat For input string: "25-beta"�[m
2025-07-14T15:00:46.1940981Z [�[1;31mERROR�[m] �[1;31m  JettySpecificWebsocketIT.testWebSocketServletWhiteboard » NumberFormat For input string: "25-beta"�[m
2025-07-14T15:00:46.1941078Z [�[1;34mINFO�[m] 
2025-07-14T15:00:46.1941405Z [�[1;31mERROR�[m] �[1;31mTests run: 24, Failures: 0, Errors: 4, Skipped: 0�[m
2025-07-14T15:00:46.1941502Z [�[1;34mINFO�[m] 
2025-07-14T15:00:46.1941596Z [�[1;34mINFO�[m] 
2025-07-14T15:00:46.1941942Z [�[1;34mINFO�[m] �[1m--- �[0;32mfailsafe:3.2.2:verify�[m �[1m(verify)�[m @ �[36morg.apache.felix.http.jetty12�[0;1m ---�[m
2025-07-14T15:00:46.1942198Z [�[1;34mINFO�[m] �[1m------------------------------------------------------------------------�[m
2025-07-14T15:00:46.1942329Z [�[1;34mINFO�[m] �[1mReactor Summary:�[m
2025-07-14T15:00:46.1942423Z [�[1;34mINFO�[m] 
2025-07-14T15:00:46.1942724Z [�[1;34mINFO�[m] Apache Felix Http Base 5.1.17-SNAPSHOT ............. �[1;32mSUCCESS�[m [ 11.340 s]
2025-07-14T15:00:46.1943010Z [�[1;34mINFO�[m] Apache Felix Http Bridge 6.0.1-SNAPSHOT ............ �[1;32mSUCCESS�[m [  2.062 s]
2025-07-14T15:00:46.1943310Z [�[1;34mINFO�[m] Apache Felix Http Inventory Printer 1.0.3-SNAPSHOT . �[1;32mSUCCESS�[m [  0.612 s]
2025-07-14T15:00:46.1943613Z [�[1;34mINFO�[m] Apache Felix Http Integration Tests 0.0.3-SNAPSHOT . �[1;32mSUCCESS�[m [07:37 min]
2025-07-14T15:00:46.1943897Z [�[1;34mINFO�[m] Apache Felix Http Wrappers 6.1.1-SNAPSHOT .......... �[1;32mSUCCESS�[m [  2.700 s]
2025-07-14T15:00:46.1944173Z [�[1;34mINFO�[m] Apache Felix Http Jetty 12.x 1.0.37-SNAPSHOT ....... �[1;31mFAILURE�[m [ 35.428 s]
2025-07-14T15:00:46.1944437Z [�[1;34mINFO�[m] Apache Felix Http Proxy 6.0.0-SNAPSHOT ............. �[1;33mSKIPPED�[m
2025-07-14T15:00:46.1944698Z [�[1;34mINFO�[m] Apache Felix Http Samples - Whiteboard 3.0.0-SNAPSHOT �[1;33mSKIPPED�[m
2025-07-14T15:00:46.1944951Z [�[1;34mINFO�[m] Apache Felix Servlet API 6.1.1-SNAPSHOT ............ �[1;33mSKIPPED�[m
2025-07-14T15:00:46.1945274Z [�[1;34mINFO�[m] Apache Felix Http SSL Filter 2.0.3-SNAPSHOT ........ �[1;33mSKIPPED�[m
2025-07-14T15:00:46.1945584Z [�[1;34mINFO�[m] Apache Felix Http Webconsole Plugin 1.2.3-SNAPSHOT . �[1;33mSKIPPED�[m
2025-07-14T15:00:46.1945875Z [�[1;34mINFO�[m] Apache Felix Http Reactor TODO remove this change 7-SNAPSHOT �[1;33mSKIPPED�[m

on detail

46.1910860Z java.lang.NumberFormatException: For input string: "25-beta"
2025-07-14T15:00:46.1911133Z 	at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:67)
2025-07-14T15:00:46.1911388Z 	at java.base/java.lang.Integer.parseInt(Integer.java:565)
2025-07-14T15:00:46.1911536Z 	at java.base/java.lang.Integer.parseInt(Integer.java:662)
2025-07-14T15:00:46.1911820Z 	at org.awaitility.core.JavaVersionDetector.getJavaMajorVersion(JavaVersionDetector.java:21)
2025-07-14T15:00:46.1912213Z 	at org.awaitility.core.LambdaErrorMessageGenerator.getLambdaDetectionClassName(LambdaErrorMessageGenerator.java:86)
2025-07-14T15:00:46.1912538Z 	at org.awaitility.core.LambdaErrorMessageGenerator.isLambdaClass(LambdaErrorMessageGenerator.java:30)
2025-07-14T15:00:46.1912935Z 	at org.awaitility.core.CallableCondition$ConditionEvaluationWrapper.generateDescriptionPrefix(CallableCondition.java:120)
2025-07-14T15:00:46.1913278Z 	at org.awaitility.core.CallableCondition$ConditionEvaluationWrapper.getMatchMessage(CallableCondition.java:110)
2025-07-14T15:00:46.1913584Z 	at org.awaitility.core.CallableCondition$ConditionEvaluationWrapper.eval(CallableCondition.java:101)
2025-07-14T15:00:46.1913833Z 	at org.awaitility.core.ConditionAwaiter$ConditionPoller.call(ConditionAwaiter.java:248)
2025-07-14T15:00:46.1914076Z 	at org.awaitility.core.ConditionAwaiter$ConditionPoller.call(ConditionAwaiter.java:235)
2025-07-14T15:00:46.1914265Z 	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:328)
2025-07-14T15:00:46.1914543Z 	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1090)
2025-07-14T15:00:46.1914800Z 	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:614)
2025-07-14T15:00:46.1914930Z 	at java.base/java.lang.Thread.run(Thread.java:1474)
2025-07-14T15:00:46.1914939Z 
2025-07-14T15:00:46.1915486Z [�[1;31mERROR�[m] org.apache.felix.http.jetty.it.JettySpecificWebsocketIT.testWebSocketServletWhiteboard -- Time elapsed: 0.269 s <<< ERROR!
2025-07-14T15:00:46.1915727Z java.lang.NumberFormatException: For input string: "25-beta"
2025-07-14T15:00:46.1915992Z 	at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:67)
2025-07-14T15:00:46.1916199Z 	at java.base/java.lang.Integer.parseInt(Integer.java:565)
2025-07-14T15:00:46.1916341Z 	at java.base/java.lang.Integer.parseInt(Integer.java:662)
2025-07-14T15:00:46.1916617Z 	at org.awaitility.core.JavaVersionDetector.getJavaMajorVersion(JavaVersionDetector.java:21)
2025-07-14T15:00:46.1917013Z 	at org.awaitility.core.LambdaErrorMessageGenerator.getLambdaDetectionClassName(LambdaErrorMessageGenerator.java:86)
2025-07-14T15:00:46.1917331Z 	at org.awaitility.core.LambdaErrorMessageGenerator.isLambdaClass(LambdaErrorMessageGenerator.java:30)
2025-07-14T15:00:46.1917826Z 	at org.awaitility.core.CallableCondition$ConditionEvaluationWrapper.generateDescriptionPrefix(CallableCondition.java:120)
2025-07-14T15:00:46.1918179Z 	at org.awaitility.core.CallableCondition$ConditionEvaluationWrapper.getMatchMessage(CallableCondition.java:110)
2025-07-14T15:00:46.1918479Z 	at org.awaitility.core.CallableCondition$ConditionEvaluationWrapper.eval(CallableCondition.java:101)
2025-07-14T15:00:46.1918727Z 	at org.awaitility.core.ConditionAwaiter$ConditionPoller.call(ConditionAwaiter.java:248)
2025-07-14T15:00:46.1918976Z 	at org.awaitility.core.ConditionAwaiter$ConditionPoller.call(ConditionAwaiter.java:235)
2025-07-14T15:00:46.1919161Z 	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:328)
2025-07-14T15:00:46.1919429Z 	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1090)
2025-07-14T15:00:46.1919695Z 	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:614)
2025-07-14T15:00:46.1919825Z 	at java.base/java.lang.Thread.run(Thread.java:1474)
2025-07-14T15:00:46.1919831Z 
2025-07-14T15:00:46.1920371Z [�[1;31mERROR�[m] org.apache.felix.http.jetty.it.JettySpecificWebsocketIT.testWebSocketServletHttpService -- Time elapsed: 0.263 s <<< ERROR!
2025-07-14T15:00:46.1920535Z java.lang.NumberFormatException: For input string: "25-beta"
2025-07-14T15:00:46.1920799Z 	at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:67)
2025-07-14T15:00:46.1920940Z 	at java.base/java.lang.Integer.parseInt(Integer.java:565)
2025-07-14T15:00:46.1921084Z 	at java.base/java.lang.Integer.parseInt(Integer.java:662)
2025-07-14T15:00:46.1921463Z 	at org.awaitility.core.JavaVersionDetector.getJavaMajorVersion(JavaVersionDetector.java:21)
2025-07-14T15:00:46.1921853Z 	at org.awaitility.core.LambdaErrorMessageGenerator.getLambdaDetectionClassName(LambdaErrorMessageGenerator.java:86)
2025-07-14T15:00:46.1922174Z 	at org.awaitility.core.LambdaErrorMessageGenerator.isLambdaClass(LambdaErrorMessageGenerator.java:30)
2025-07-14T15:00:46.1922573Z 	at org.awaitility.core.CallableCondition$ConditionEvaluationWrapper.generateDescriptionPrefix(CallableCondition.java:120)
2025-07-14T15:00:46.1922916Z 	at org.awaitility.core.CallableCondition$ConditionEvaluationWrapper.getMatchMessage(CallableCondition.java:110)
2025-07-14T15:00:46.1923208Z 	at org.awaitility.core.CallableCondition$ConditionEvaluationWrapper.eval(CallableCondition.java:101)
2025-07-14T15:00:46.1923457Z 	at org.awaitility.core.ConditionAwaiter$ConditionPoller.call(ConditionAwaiter.java:248)
2025-07-14T15:00:46.1923696Z 	at org.awaitility.core.ConditionAwaiter$ConditionPoller.call(ConditionAwaiter.java:235)
2025-07-14T15:00:46.1923876Z 	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:328)
2025-07-14T15:00:46.1924147Z 	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1090)
2025-07-14T15:00:46.1924402Z 	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:614)
2025-07-14T15:00:46.1924526Z 	at java.base/java.lang.Thread.run(Thread.java:1474)
2025-07-14T15:00:46.1924531Z 

@stbischof

Copy link
Copy Markdown
Contributor

awaitility/awaitility#296

@paulrutter

Copy link
Copy Markdown
Contributor Author

can you also do a change in scr to trigger this test

Will do tomorrow 👍

- continue-on-error: true to allow building other modules after a failed one
- Change SCR to trigger CI
@stbischof

Copy link
Copy Markdown
Contributor

might be interesting to du parallel build for matrix java-version x module

like here in osgi repo
https://github.com/osgi/osgi/blob/0b278b1d315138602cd480072e77bd5a3b07fb10/.github/workflows/cibuild.yml#L182

@paulrutter

Copy link
Copy Markdown
Contributor Author

Results of the latest run, including SCR:

SCR
Due to failure in framework.

WARNING: A terminally deprecated method in sun.misc.Unsafe has been called
WARNING: sun.misc.Unsafe::staticFieldOffset has been called by org.apache.felix.framework.util.SecureAction (file:/home/runner/.m2/repository/org/apache/felix/org.apache.felix.framework/7.0.1/org.apache.felix.framework-7.0.1.jar)
WARNING: Please consider reporting this to the maintainers of class org.apache.felix.framework.util.SecureAction
WARNING: sun.misc.Unsafe::staticFieldOffset will be removed in a future release

Framework

WARNING: sun.misc.Unsafe::staticFieldOffset has been called by org.apache.felix.framework.util.SecureAction (file:/home/runner/.m2/repository/org/apache/felix/org.apache.felix.framework/7.0.5/org.apache.felix.framework-7.0.5.jar)
WARNING: Please consider reporting this to the maintainers of class org.apache.felix.framework.util.SecureAction
WARNING: sun.misc.Unsafe::staticFieldOffset will be removed in a future release
org.osgi.framework.BundleException: Unable to resolve slf4j.api [13](R 13.0): missing requirement [slf4j.api [13](R 13.0)] osgi.extender; (&(osgi.extender=osgi.serviceloader.processor)(version>=1.0.0)(!(version>=2.0.0))) Unresolved requirements: [[slf4j.api [13](R 13.0)] osgi.extender; (&(osgi.extender=osgi.serviceloader.processor)(version>=1.0.0)(!(version>=2.0.0)))]
	at org.apache.felix.framework.Felix.resolveBundleRevision(Felix.java:4398)
	at org.apache.felix.framework.Felix.startBundle(Felix.java:2308)
	at org.apache.felix.framework.Felix.setActiveStartLevel(Felix.java:1566)
	at org.apache.felix.framework.FrameworkStartLevelImpl.run(FrameworkStartLevelImpl.java:297)
	at java.base/java.lang.Thread.run(Thread.java:1474)

HTTP
Warning:

Mockito is currently self-attaching to enable the inline-mock-maker. This will no longer work in future releases of the JDK. Please add Mockito as an agent to your build as described in Mockito's documentation: https://javadoc.io/doc/org.mockito/mockito-core/latest/org.mockito/org/mockito/Mockito.html#0.3
WARNING: A Java agent has been loaded dynamically (/home/runner/.m2/repository/net/bytebuddy/byte-buddy-agent/1.17.5/byte-buddy-agent-1.17.5.jar)
WARNING: If a serviceability tool is in use, please run with -XX:+EnableDynamicAgentLoading to hide this warning
WARNING: If a serviceability tool is not in use, please run with -Djdk.instrument.traceUsage for more information
WARNING: Dynamic loading of agents will be disallowed by default in a future release

@tjwatson

Copy link
Copy Markdown
Member
WARNING: sun.misc.Unsafe::staticFieldOffset has been called by org.apache.felix.framework.util.SecureAction (file:/home/runner/.m2/repository/org/apache/felix/org.apache.felix.framework/7.0.5/org.apache.felix.framework-7.0.5.jar)
WARNING: Please consider reporting this to the maintainers of class org.apache.felix.framework.util.SecureAction
WARNING: sun.misc.Unsafe::staticFieldOffset will be removed in a future release

I discussed this at https://www.mail-archive.com/dev%40felix.apache.org/msg57202.html

But I didn't have any luck getting feedback on using a common solution between Equinox and Felix (and maybe others). Therefore I only integrated it into Equinox to get rid of the use of Unsafe for the URL singleton management. If someone from Felix would like to adopt the same strategy as I did in Equinox I think it would be good so the two framework's can live in the same JVM without cratering the URL singletons.

@paulrutter

Copy link
Copy Markdown
Contributor Author

Thanks @tjwatson, from my point of view we should indeed consider adopting the same approach as you mentioned in osgi/osgi#226 (comment).
Hopefully others can weigh in on this as well, given that Java 25 will be LTS soon-ish.

@stbischof

Copy link
Copy Markdown
Contributor

common solution between Equinox and Felix .... And springboot would be really best way to solve.

@tjwatson

tjwatson commented Jul 15, 2025

Copy link
Copy Markdown
Member

common solution between Equinox and Felix .... And springboot would be really best way to solve.

I don't disagree but I have my doubts the SpringBoot URL factories will be open to play well with others. Worth a try if you already have a good contribution relationship with the Spring project to bring up the issue.

But I first suggest we get Felix and Equinox to play well with each other to prove out the approach.

@nroduit

nroduit commented Aug 10, 2025

Copy link
Copy Markdown
Contributor

In addition to the changes of removing the use of sun.misc.Unsafe, all code in Framework using SecurityManager should be removed, since SecurityManager has been completely disabled from Java 24 onwards.

@stbischof

Copy link
Copy Markdown
Contributor

I disagree with your comment in Security manager.
There are users that use lower Versions if java and need Security Management.

In all cases where Security Managemer is uses we check Existense before we use that. So no execution in Versions where Security Manager is remived.

@mattrpav

mattrpav commented Oct 1, 2025

Copy link
Copy Markdown

With the SecurityManager removal, it makes it difficult to support wide JDK LTS version ranges. I suggest making two supported branch streams with JDK LTS version alignment.

There are two issues with trying to support a wide range of JDK versions:

  1. SecurityManager class is not present in JDK 25
  2. JAAS API permanently changes in JDK 25, and is not backward compatible in JDK 17
    a. No Subject.current() present in JDK 11/17 due to the ThreadLocal to ScopedValue conv

The approach we are looking at taking in Apache ActiveMQ and Apache Karaf is to have branches with JDK supported ranges::

branch-a: Supported Java: JDK 17 to 21 (Apache Karaf is able to do JDK 11 to JDK 21)
branch-b: Supported Java: JDK 21 to 25

It does to appear that it is physically possible to mismatch JAAS API across JDK 11-25 or JDK 17-25 b/c of the JAAS API change. One side sets a ThreadLocal and uses doAs() and the newer API uses ScopedValue and runAs() methods on the Subject class.

see: https://docs.oracle.com/en/java/javase/21/docs/api/java.base/javax/security/auth/Subject.html

@tjwatson

tjwatson commented Oct 1, 2025

Copy link
Copy Markdown
Member
  1. SecurityManager class is not present in JDK 25

Is the class completely gone? I would be surprised because I would have expected loads of class not founds when running Equinox on Java 25, but we don't observe that.

@laeubi

laeubi commented Oct 1, 2025

Copy link
Copy Markdown

@mattrpav Just wanted to note that JDT has now new support for multi-release jars that maps nicely to what we have in maven.

Multi-Release Jars are a perfect fit for such kind of support such JDK dependent changes, then one only need a SecurityManagerFacade that is a multi-release type where depending on the JVM version either use security manager or make it a no-op on JDK25+

@mattrpav

mattrpav commented Oct 1, 2025

Copy link
Copy Markdown

@tjwatson I mispoke-- JDK 25 disables the SecurityManager by default and custom SecurityManages cannot be installed.

@laeubi MRJ is a good idea, will check that out. Have you solved for how to do JDK-version-specific unit tests in a single Maven module? If so, I'd love to see a sample configuration.

@laeubi

laeubi commented Oct 1, 2025

Copy link
Copy Markdown

MRJ is a good idea, will check that out. Have you solved for how to do JDK-version-specific unit tests in a single Maven module? If so, I'd love to see a sample configuration.

Let me know if you need any pointer or support, we would need something similar for equinox on the long run.

Regarding testing the most useful these days is a matrix build what uses different native JVMs... of course one can write MR-Test cases as well its just a bit more setup.

@tjwatson

tjwatson commented Oct 1, 2025

Copy link
Copy Markdown
Member

Let me know if you need any pointer or support, we would need something similar for equinox on the long run.

I have a distaste for MRJ. If we create a SecurityManagerFacade then I would prefer that to just load the right class depending on the Java version behind that instead of being hidden behind class loader MRJ stuff.

@mattrpav

mattrpav commented Oct 1, 2025

Copy link
Copy Markdown

Regarding testing the most useful these days is a matrix build what uses different native JVMs... of course one can write MR-Test cases as well its just a bit more setup.

Yeah, the how-to-execute-tests is the issue I'm running into. Creating a MR-jar for compiling and packaging test classes seems straight-forward. The hang-up comes in as far as how to instruct the surefire plugin to execute those tests. ASFAIK, would require two separate Maven profiles (kludgy-- as the surefire configurations would need to be kept in sync b/w the two profiles) for listing include/exclude of class test names based on JDK version. Punting to use separate Maven modules by JDK version seems less than ideal.

@mattrpav

mattrpav commented Oct 1, 2025

Copy link
Copy Markdown

I have a distaste for MRJ

Anything specific? I'm looking at using a MRJ for activemq-client to use that for the Virtual Thread classes that need JDK 21+.

@tjwatson

tjwatson commented Oct 1, 2025

Copy link
Copy Markdown
Member

I have a distaste for MRJ

Anything specific? I'm looking at using a MRJ for activemq-client to use that for the Virtual Thread classes that need JDK 21+.

It has been a while since I looked into them seriously. But the first blocker from me was source code debugging and what the source JAR looks like for the release. It was a nightmare to debug. Maybe all that is fixed by now. But it seemed far more simple to just choose the class to load myself in code.

@mattrpav

Copy link
Copy Markdown

Many other projects settled on using a MR jar and a SubjectShim class that wraps the differences in the JAAS api for resolving the Subject

@paulrutter

Copy link
Copy Markdown
Contributor Author

Given this comment from @tjwatson, i doubt MR's are the way forward.

  • Reflection could work, but bloat the codebase. Not ideal, but could work.
  • two branches seems like a viable solution; the main branch could contain the "latest and greatest" support (JDK 25, sans SecurityManager), while maintaining a branch for older JDK's. That the approach we're taking for the HTTP subproject for EE10 and EE11 as well. This would be my preferred approach.
    ** maintaining two branches carries a maintenance burden, but at least the core framework doesn't change often, so that risk we can probably afford to have.

I would like to get some more opinions (and hopefully consensus) on this before we start work in either direction.

@mbien

mbien commented Aug 25, 2026

Copy link
Copy Markdown
Member
  • two branches seems like a viable solution

fwiw: JDK recommends the two branch model too https://openjdk.org/jeps/14

paulrutter and others added 3 commits August 29, 2026 20:01
…Java-25-LTS

# Conflicts:
#	.github/workflows/maven-ci.yml
#	http/itest/pom.xml
Java SE 24 permanently disabled the Security Manager (JEP 486), so
System.getSecurityManager() always returns null and none of the permission
enforcement in Felix could ever run. Passing -Djava.security.manager=allow is
now a fatal VM startup error, which prevented the framework tests from running
on JDK 25 at all.

The OSGi API types are kept (AdminPermission, ServicePermission,
PackagePermission, BundlePermission, CapabilityPermission, AdaptPermission,
Bundle.hasPermission, ProtectionDomain, BundleProtectionDomain and
ext.SecurityProvider), so bundles referencing them still compile and link. Only
the enforcement is removed.

framework:
- Felix.init() no longer installs a SecurityManager. Setting
  org.osgi.framework.security now fails fast instead of silently launching
  without the security the launcher asked for.
- SecureAction: all 65 doPrivileged wrappers collapsed to their direct calls and
  the Actions dispatch class dropped (2113 -> 656 lines).
- SecurityManagerEx no longer extends SecurityManager; it uses StackWalker,
  the supported replacement for getClassContext(), which yields frames in the
  same order. This raises felix.java.version to 9, the lowest level the module
  still builds at.
- Permission checks removed from BundleImpl, BundleContextImpl,
  BundleWiringImpl, EventDispatcher, WovenClassImpl, StatefulResolver,
  ExtensionManager, ServiceRegistrationImpl, FrameworkStartLevelImpl,
  FrameworkWiringImpl, URLHandlersBundleStreamHandler and
  BundleProtectionDomain. Every removed branch was already unreachable without
  a SecurityManager, so behaviour is unchanged.
- Dropped the two URLHandlersTest SecurityManager tests; without a
  SecurityManager they duplicated the two tests they wrapped.
- asm-all 5.2 cannot read class files newer than Java 8 and broke the weaving
  hook tests; replaced with asm/asm-tree 9.8.

framework.security: removed. The module existed only to implement the
SecurityManager based SecurityProvider (PermissionAdmin,
ConditionalPermissionAdmin). configadmin depends on the released 2.8.3 artifact,
not on this module.

scr, webconsole, gogo: removed the remaining getSecurityManager() gates and
doPrivileged wrappers. Bumped gogo to mockito-core 5.18.0, as 5.17.0 ships a
byte-buddy that cannot mock on JVM 25.

CI: build on JDK 25 rather than 25-ea.

Verified on JDK 25 against a JDK 21 control run on the same tree: framework,
scr (170 tests), webconsole (23 tests) and gogo now have the same results on
both JDKs. The residual failures are pre-existing Windows-only issues
(a fixture filename containing invalid NTFS characters, and deleteDir file
locking) that fail identically on JDK 21.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Follow-up to the SecurityManager removal, covering the non-SecurityManager
problems that stop modules building or testing on JDK 25.

Stale parent poms are the root cause of most of them. Several modules declare
felix-parent 2.1-7 with relativePath ../pom/pom.xml, but the local pom is
10-SNAPSHOT, so the relativePath does not match and Maven silently resolves the
old released parent from Maven Central instead. Those parents hardcode
felix.java.version 6 or 7 (javac 25 rejects release < 8) and pin
maven-surefire-plugin 2.x, which cannot parse the JDK 25 version string and dies
with an NPE before running any test. Bumping the parent to felix-parent 9 fixes
both at once, rather than overriding the compiler and plugin settings per module:

- bundlerepository (2.1), configadmin (6), connect (5), log.extension (5),
  resolver (5), utils (5) -> felix-parent 9.
- bundlerepository additionally declares junit and mockito explicitly, because
  felix-parent 2.1 supplied them to every module and felix-parent 9 does not.
  mockito-all 1.x is replaced by mockito-core, as its bundled cglib cannot
  generate classes on JDK 25.
- resolver: mockito-all 1.10.19 -> mockito-core 5.18.0, for the same reason.

Compiler levels below 8 are rejected outright by javac 25:
- log, log.extension: maven.compiler.source/target 1.7 -> 8.
- connect (1.6), bundlerepository (1.5) and the three examples/extenderbased.*
  modules (1.5) -> 8.

configadmin: UpdateThread.terminate() called Thread.stop() when a worker failed
to join within 5 seconds. Thread.stop() has thrown UnsupportedOperationException
since Java 20, so that path could only turn a slow shutdown into a failed one.
It now interrupts the worker instead.

framework.tck: tck.bndrun still required assertj-core [3.27.3,3.27.4) after the
dependency was bumped to 3.27.7, so the bndrun could not resolve and the TCK
failed on every JDK, not just 25.

CI: build bundlerepository, configadmin, connect, log.extension, resolver and
utils, so the modules changed here are covered by the matrix.

README: document that the framework no longer supports the OSGi security layer
and which Java versions CI covers.

Verified on JDK 25 (Corretto 25.0.2), each against a JDK 21 control:
utils 108 tests, configadmin 111, bundlerepository 42, resolver 28, plus connect,
log, log.extension and examples building clean.

Not addressed here: iPOJO (a removal PR is open), eventadmin (not actively
maintained; its integration tests fetch a bundle from the long-dead
repository.springsource.com and its maven-bundle-plugin predates a bnd fix for a
TreeMap.computeIfAbsent ConcurrentModificationException on Java 9+), and the
wider bnd/maven-bundle-plugin upgrade, which only matters once a module is
actually compiled at release 25.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
An audit of the workflow against the modules changed in this PR found three gaps:

- gogo was listed for pull_request but not for push, so a push to master touching
  only gogo never triggered a build.
- framework.tck appeared in neither trigger and had no path filter. The TCK step is
  gated on the framework filter, so a change to the TCK alone - such as the
  tck.bndrun assertj range fix in this PR - did not trigger a build at all. It is now
  part of the framework filter and both triggers.
- examples is changed here but was not covered; it now has a filter and a build step.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@paulrutter

paulrutter commented Aug 29, 2026

Copy link
Copy Markdown
Contributor Author

Status update: SecurityManager removed, JDK 25 build blockers fixed, TCK green, framework at 8.0.0

Picking up the two-branch approach discussed in #433 (comment) and confirmed by @mbien's JEP 14 reference: this branch drops the Security Manager entirely and fixes what actually breaks on JDK 25. The branch has also been synced with master.

Everything below was verified locally on JDK 25.0.2, each time against a JDK 21 control run on the same tree, so that pre-existing and platform-specific failures were not misattributed to JDK 25.

What actually blocked JDK 25

Worth recording, because it was much narrower than expected:

  1. framework/pom.xml passed -Djava.security.manager=allow. On JDK 25 that is a fatal VM startup error (JEP 486), so zero tests ran — this one flag was masking everything else.
  2. Once removed, the only JDK-25-attributable failures were the two URLHandlersTest SecurityManager tests.

Probing the API directly on JDK 25: only System.setSecurityManager actually throws. AccessController.doPrivileged, getContext, Policy.getPolicy, ProtectionDomain — and even subclassing SecurityManager — all still work. So the framework's sole production blocker was Felix.init(); the rest is dead code that could never execute again.

SecurityManager removal (−8,000 lines)

Enforcement is gone; the OSGi API types are kept, so bundles referencing AdminPermission, ServicePermission, PackagePermission, Bundle.hasPermission, ProtectionDomain etc. still compile and resolve.

  • Felix.init() no longer installs a Security Manager. Setting org.osgi.framework.security now fails fast with a SecurityException rather than silently launching without the security the launcher asked for.
  • SecureAction: 2113 → 656 lines; all 65 doPrivileged wrappers collapsed to their direct calls, the Actions dispatch class deleted.
  • SecurityManagerEx no longer extends SecurityManager — it now uses StackWalker, the supported replacement for getClassContext(), which yields frames in the same order. No extends SecurityManager remains anywhere.
  • Enforcement removed from BundleImpl, BundleContextImpl, BundleWiringImpl, EventDispatcher, WovenClassImpl, StatefulResolver, ExtensionManager, ServiceRegistrationImpl, FrameworkStartLevelImpl, FrameworkWiringImpl, URLHandlersBundleStreamHandler, BundleProtectionDomain, plus scr, webconsole and gogo. Every removed branch was already unreachable without a Security Manager, so behaviour is unchanged.
  • framework.security removed — it existed only to implement the SM-based SecurityProvider.

felix.java.version for framework is now 9 — the lowest level it still builds at. To be explicit: JDK 25 did not force this; the old SecurityManagerEx.getClassContext() works fine on 25. The floor comes from replacing it with StackWalker so that no extends SecurityManager is left. Staying on 8 is possible if we keep that class — happy to go either way.

Two pre-existing framework bugs found by the TCK — now split out into #554

Once the TCK could actually launch (see below) it reported 33 errors, all from FilterImpl.WrapperCapability. Both were introduced by 466eb93 "[fw] reduce warning related to types Classes" — a generics cleanup — and are unrelated to this PR. They are on master today.

These are now proposed separately against master in #554, with regression tests, since they affect released versions independently of any Java version work. This branch carries the same fix so that its TCK run can pass; that will drop out once #554 merges.

1. Filter.matches(Map) is broken for any non-empty map. The constructor lost its assignment into a stray empty if block:

m_map = Collections.emptyMap();
if(map != null ) {
}
m_map.putAll(map);

m_map is an immutable empty map, so putAll throws UnsupportedOperationException (or NPE when map is null). It previously read m_map = (map == null) ? Collections.EMPTY_MAP : map;. This has been broken on master since April 2025.

2. WrapperCapability(ServiceReference) requires an OSGi 1.10 method. It was rewritten to new DictionaryToMap(sr.getProperties(), false). ServiceReference.getProperties() was only added in Core 1.10 and is not implemented by every ServiceReference — the TCK's own mock throws UnsupportedOperationException. Restored to the getPropertyKeys()/getProperty() loop.

See #554 for the details, the fix and the regression tests. A backport may be worth considering, since Filter.matches(Map) is unusable in released versions.

The TCK was failing on every JDK — three stacked causes

framework.tck has been red for a while, and none of it was about Java 25:

  1. tck.bndrun required assertj-core [3.27.3,3.27.4) after the dependency was bumped to 3.27.7 in Bump org.assertj:assertj-core from 3.27.3 to 3.27.7 in /framework.tck #478, so the bndrun could not resolve at all.
  2. With that fixed it resolved but died in the bnd launcher: aQute.launcher.Launcher.activate() calls Policy.setPolicy() unguarded, which Java 24+ rejects. bnd has since wrapped that in a catch for exactly this reason; the tester was pinned to biz.aQute.junit 6.4.1, predating the fix, while the bnd plugins were on 7.1.0. Both moved to 7.4.0, matching the bndlib version the repository already uses.
  3. Then assertj-core 3.27.7 could not resolve: it imports net.bytebuddy [1.18.0,2.0.0) but byte-buddy was pinned at 1.17.5 — the same omission as (1), from the same dependabot bump. Moved to 1.18.12.

Plus the two FilterImpl bugs above. The OSGi Core R8 TCK now passes on JDK 25 (8.0.0 is the latest published version of org.osgi.test.cases.framework, so we are on the current TCK).

Causes 1 and 3 break the TCK on every JDK, not just 25, so they are also part of #554 to make that PR verifiable against master. Cause 2 stays here, being specific to Java 24 and later.

CI was reporting failing builds as green

continue-on-error: true on the SCR, HTTP and Framework steps made GitHub report those steps as successful even when Maven failed. On one run the "Felix HTTP" step shows conclusion: success while its log contains BUILD FAILURE. Removed, which immediately exposed a real JDK 25 failure it had been hiding:

  • http/jetty and http/jetty12 provision ASM 9.7 bundles into the pax-exam container. ASM 9.7 only understands class files up to Java 23, so JakartaSpecificWebsocketIT failed inside Jetty's websocket component with Unsupported class file major version 69, taking down the whole http reactor. Now provisions ASM 9.8.

Also fixed: gogo was in the pull_request trigger but not push; framework.tck was in neither trigger and had no path filter, so TCK-only changes never triggered a build at all. All modules changed here are now covered, and a concurrency group cancels superseded PR runs.

Other JDK 25 blockers fixed

http/jetty, http/jetty12 provisioned ASM 9.7 into the pax-exam container; 9.7 cannot read class file 69, so websocket ITs failed with Unsupported class file major version 69. Now 9.8
gogo mockito-core 5.17.0 to 5.18.0; 5.17's byte-buddy cannot mock on JVM 25
framework asm-all 5.2 to asm/asm-tree 9.8; 5.2 cannot read class files newer than Java 8
framework.tck assertj range, byte-buddy range, bnd 7.4.0, duplicate dependency (see above)

Scope

This PR is deliberately limited to the modules that were already in the CI matrix and genuinely broke on JDK 25. Work that turned out to be unrelated has been split into its own pull requests, stacked on this branch:

log was dropped entirely: it needed no change. Its maven.compiler.source/target of 1.7 is overridden by felix-parent's release configuration, and it builds on JDK 25 unmodified, which was verified.

Version bumps

Versions follow whether a module's code actually changed:

module code changed version
framework 16 source files 7.1.0 to 8.0.0
scr 5 source files 2.2.19 to 2.3.0
webconsole 3 source files 5.0.19 to 5.1.0
gogo.runtime 1 source file 1.1.7 to 1.2.0
http test code only unchanged
framework.tck, main, main.distribution none unchanged

The framework's major bump rests on the removal of the OSGi security layer, a documented behaviour change, and therefore holds independently of the minimum Java version discussion. Even keeping the baseline at 8, that removal alone warrants it. Its manifest now reads:

Bundle-Version: 8.0.0.SNAPSHOT
Require-Capability: osgi.ee;filter:="(&(osgi.ee=JavaSE)(version=9))"

Note that tck.bndrun pinned -runfw to [7.0.0,8), which would have excluded the new framework, so that range moves to [8.0.0,9).

scr, webconsole and gogo.runtime get minor bumps rather than major ones: no exported API differs, and the removed code only ran with a Security Manager installed, which cannot happen on the JDKs this line targets.

framework.tck, main and main.distribution keep their versions, since they have no code changes; only their reference to the framework moves to 8.0.0-SNAPSHOT, which the build requires. Historically these have been released in lockstep with the framework, so if the project prefers to keep that convention they should be bumped too.

No exported package versions were changed. Everything the framework exports is org.osgi.*, whose versions are set by the specification rather than by us, and the permission API is deliberately kept unchanged, so no exported package's API actually differs.

Results on JDK 25

framework 118 tests, scr 170, webconsole 23, plus gogo, http, and the OSGi Core TCK, which was re-run and still passes with the framework at 8.0.0. In every module the results match the JDK 21 control run exactly. The residual failures are pre-existing platform-specific ones (a test fixture filename containing characters invalid on NTFS, and deleteDir file locking) that fail identically on JDK 21 and pass on Linux.

Deliberately not in scope

Separate: sun.misc.Unsafe and the URL singletons

@tjwatson's point in #433 (comment) is not a JDK 25 blocker — the Unsafe block is guarded by catch (Throwable) with a setAccessible fallback, so on 25 it only warns. It is a JDK 26+ and framework-interop concern, so I have kept it out of this PR and opened #552 as a draft prototype using plurl. There is an unresolved licensing question there (the vendored sources carry EPL-2.0 headers while plurl's LICENSE and pom say Apache-2.0) — @tjwatson, your input would be very welcome on that PR.

🤖 Generated with Claude Code

paulrutter and others added 6 commits August 29, 2026 22:14
Removes continue-on-error from the SCR, HTTP and Framework CI steps. It was
reporting those steps as successful even when Maven failed, which hid a real JDK 25
failure in HTTP: the run for the previous commit showed "BUILD SUCCESS" for the step
while the log contained BUILD FAILURE.

What it was hiding, and the follow-on TCK failures:

- http/jetty and http/jetty12 provision ASM 9.7 bundles into the pax-exam container.
  ASM 9.7 only understands class files up to Java 23, so on JDK 25
  JakartaSpecificWebsocketIT failed inside Jetty's websocket component with
  "Unsupported class file major version 69". Provision ASM 9.8 instead. This surfaced
  now because the jetty module was re-enabled in this branch after having been
  commented out.

- framework.tck: with the assertj range corrected the bndrun resolves, and the run
  then failed in the bnd launcher with "Setting a system-wide Policy object is not
  supported". aQute.launcher.Launcher.activate() called Policy.setPolicy()
  unguarded; bnd has since wrapped that in a catch specifically because Java 24
  rejects it. The tester bundle was pinned to biz.aQute.junit 6.4.1, which predates
  the fix, while the bnd plugins were on 7.1.0. Move both to 7.4.0, matching the
  bndlib version the repository already uses elsewhere.

- framework.tck declared junit-platform-launcher twice, which Maven warns is
  malformed and may reject in future. Removed the duplicate.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The "TODO remove this change" suffixes were added to the framework, http and scr
project names purely to make the path filters fire while this branch was being
developed. Those modules now have real changes, so the markers are no longer needed
and the names are restored.

Also drops BundleImpl.m_smEx and m_classloader. The AdaptPermission check that used
the caller class context is gone, leaving both fields unread while the class
initialiser still allocated a SecurityManagerEx.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… the TCK

With the assertj range corrected the bndrun resolves, but the TCK then failed to
start assertj-core:

    Unable to resolve assertj-core [8](R 8.0): missing requirement
    osgi.wiring.package; (&(osgi.wiring.package=net.bytebuddy)
    (version>=1.18.0)(!(version>=2.0.0)))

assertj-core 3.27.7 imports net.bytebuddy [1.18.0,2.0.0), but the TCK still pinned
byte-buddy 1.17.5. The dependency was bumped from 3.27.3 to 3.27.7 in #478 without
byte-buddy following, which is the same omission that left the bndrun requiring
assertj [3.27.3,3.27.4). Move byte-buddy to 1.18.12 in both the pom and the bndrun.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds a concurrency group so that pushing again to a branch cancels the run still in
progress for the previous commit, instead of letting the whole JDK matrix finish for
a revision nobody is waiting on.

github.head_ref is only set for pull_request events, so pushes to master fall back to
the unique run_id and are never cancelled.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…the TCK

With the TCK finally able to launch, it reported 33 errors across
BundleContextFilterTests and DivTests. Both come from FilterImpl.WrapperCapability,
which was damaged by 466eb93 ("[fw] reduce warning related to types Classes"), a
generics cleanup. These are pre-existing defects on master, not fallout from the
SecurityManager removal.

The Map constructor lost its assignment into a stray empty if block:

    m_map = Collections.emptyMap();
    if(map != null ) {
    }
    m_map.putAll(map);

so m_map was an immutable empty map and putAll threw UnsupportedOperationException
for any non-empty map, or NPE for a null one. It previously read

    m_map = (map == null) ? Collections.EMPTY_MAP : map;

which is restored. Filter.matches(Map) has therefore been broken on master since
April 2025.

The ServiceReference constructor was rewritten from reading properties one by one to
new DictionaryToMap(sr.getProperties(), false). ServiceReference.getProperties() was
only added in OSGi Core 1.10 and is not implemented by every ServiceReference; the
TCK's own mock throws UnsupportedOperationException for it. Restored to
getPropertyKeys()/getProperty(), which every implementation supports.

The OSGi Core TCK now passes on JDK 25 (8.0.0 is the latest published version).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The pull_request trigger filters on the BASE branch, and only accepted master. A
stacked pull request - one opened against another feature branch rather than master -
therefore matched neither trigger and got no CI at all, which is what happened to
PR #552.

Accept feature/** and maintenance/** as a base as well, so stacked work is built
before it is merged down.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
paulrutter and others added 2 commits August 29, 2026 23:02
…onments

Removing the security layer changes documented framework behaviour, and several
modules now declare a higher osgi.ee than before, which is resolution affecting: a
deployment that resolved against the old requirement will not resolve against the
new one.

The framework and the artifacts versioned in lockstep with it go to 8.0.0-SNAPSHOT.
Its manifest now reads:

    Bundle-Version: 8.0.0.SNAPSHOT
    Require-Capability: osgi.ee;filter:="(&(osgi.ee=JavaSE)(version=9))"

tck.bndrun pinned -runfw to [7.0.0,8), which would have excluded the new framework,
so that range moves to [8.0.0,9).

The remaining modules were compiling against an old released felix-parent resolved
from Central, because their declared parent version did not match the local pom.
Correcting that raised their compiler level as a side effect:

    utils             1.11.9 -> 2.0.0   (EE 1.7 -> 1.8)
    log                1.3.3 -> 2.0.0   (EE 1.7 -> 1.8)
    log.extension      1.0.1 -> 2.0.0   (EE 1.7 -> 1.8)
    configadmin       1.9.27 -> 2.0.0   (EE 1.7 -> 1.8)
    connect            0.2.1 -> 1.0.0   (EE 1.6 -> 1.8)
    resolver           2.1.0 -> 3.0.0   (EE 1.6 -> 1.8)
    bundlerepository  2.0.11 -> 3.0.0   (EE 1.5 -> 1.8)

Adds framework/README.md describing what differs between the 7.x and 8.x lines and
what upgrading requires, plus a changelog entry.

The OSGi Core R8 TCK passes on JDK 25 with the framework at 8.0.0.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Reverts the version bumps applied to utils, log, log.extension, connect, resolver,
bundlerepository and configadmin. Their build fixes stay; only the version changes
are withdrawn.

The reasoning for bumping them was that repairing their stale parent poms raised
their osgi.ee, which is resolution affecting. That does not hold up:

- Six of the seven have no code change at all. Their only modification is pom
  configuration, and the version recorded in a pom is the version of the next
  release, which is a release-manager decision taken against everything that lands
  before that release rather than something this change should pre-empt.
- The old execution environments were themselves accidental. Those modules compiled
  at 1.5 to 1.7 only because a stale parent version meant Maven resolved an old
  felix-parent from Central instead of the local one, so moving to 1.8 restores the
  intended level rather than deliberately dropping support.
- connect going from 0.2.1 to 1.0.0 was the least defensible: for a 0.x artifact a
  major bump conveys little, while 1.0.0 asserts API stability that nothing here
  establishes.
- configadmin's one code change, Thread.stop() to interrupt(), is a bug fix.
  Thread.stop() has thrown UnsupportedOperationException since Java 20, so the
  previous code could only fail.

The framework stays at 8.0.0-SNAPSHOT, together with framework.tck, main and
main.distribution which are versioned in lockstep with it. That bump rests on the
removal of the OSGi security layer, a documented behaviour change across 16 modified
source files, and holds independently of the execution environment.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
paulrutter and others added 5 commits August 29, 2026 23:23
Splits out work that was not about Java 25 support, and aligns version changes with
whether a module's code actually changed.

Moved to separate pull requests:

- utils, connect, bundlerepository, resolver, log.extension and the
  examples/extenderbased modules. Their builds fail on a modern JDK, but none of them
  has a code change, none was in the CI matrix, and each releases independently, so
  repairing their stale parent poms belongs in its own change.
- configadmin's Thread.stop() to interrupt() fix. Thread.stop() has thrown since Java
  20, so it is a bug fix in its own right rather than part of Java 25 support.

Dropped entirely: log needed no change. Its maven.compiler.source/target of 1.7 is
overridden by felix-parent's release configuration, and it already builds on JDK 25
unmodified. Verified.

Version changes now follow whether code changed:

- framework 7.1.0 -> 8.0.0. 16 source files changed and the OSGi security layer is
  removed.
- scr 2.2.19 -> 2.3.0, webconsole 5.0.19 -> 5.1.0, gogo.runtime 1.1.7 -> 1.2.0. Each
  has code changes removing permission enforcement. No exported API differs and the
  removed code only ran with a SecurityManager installed, which cannot happen on the
  JDKs this line targets, so a minor bump rather than a major one.
- framework.tck, main and main.distribution keep their versions. They have no code
  changes; only their reference to the framework moves to 8.0.0-SNAPSHOT, which the
  build requires.
- http keeps its version. Only test code changed there.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Removing the split-out modules from the workflow left their filter keys behind
without their path lists:

    configadmin:
          utils:
          resolver:
          ...

That is still valid YAML, as a nested mapping, which is why a parse check did not
catch it, but it is not what dorny/paths-filter expects.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Every module whose code changed now documents it where that module already keeps its
history:

- scr/changelog.txt gains a 2.3.0 entry.
- gogo/runtime/doc/changelog.txt gains a 1.1.6 to 1.2.0 entry.
- webconsole/README.md gains a 5.1.0 entry under Releases, which is where that
  project records its history rather than in a separate changelog file.

framework/doc/changelog.txt was already updated with the 8.0.0 entry. http is not
included: only its test code changed.

The webconsole Security section is left alone. It documents HTTP authentication and
CSRF, which is unrelated to the Java Security Manager.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ocal build

The TCK step failed to resolve the framework:

    Could not find artifact org.apache.felix:org.apache.felix.framework:jar:
    8.0.0-SNAPSHOT in apache.snapshots

The framework step ran clean verify, which does not install. The TCK is a separate
Maven invocation, so it resolves org.apache.felix.framework from the repository
rather than from the build that just ran. While the framework was 7.1.0-SNAPSHOT that
version existed in apache.snapshots, so resolution succeeded and the TCK quietly
exercised the published snapshot instead of the code under test. Renaming to 8.0.0
turned that silent substitution into a resolution error.

Running clean install makes the TCK test the framework this build produced, which is
what the step was always meant to do.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…sion

gogo.runtime moved to 1.2.0-SNAPSHOT, but gogo.jline still declared a dependency on
1.1.7-SNAPSHOT, which no longer exists locally and is not published:

    Could not find artifact org.apache.felix:org.apache.felix.gogo.runtime:jar:
    1.1.7-SNAPSHOT in apache.snapshots

gogo.jline is the only module referencing the snapshot; gogo.bom and gogo.command
reference the released 1.1.4 and are unaffected.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@paulrutter
paulrutter marked this pull request as ready for review August 29, 2026 22:41
paulrutter and others added 3 commits August 30, 2026 00:46
main is changed by this branch, its dependency on the framework moves to
8.0.0-SNAPSHOT, and it embeds the framework, yet nothing verified it: there was no
main path filter and no build step, so a break would only have surfaced at release
time.

Building it locally first showed it does not build on a modern JDK at all, for the
same reason as the modules in the split-out build repair change: it declares
felix-parent 6, which does not match the local pom, so Maven resolves the released
parent from Central. That parent brings in ianal-maven-plugin 1.0-alpha-1, which
reflects into java.io and is blocked from Java 16 on:

    Unable to make private java.io.File(java.lang.String,java.io.File) accessible:
    module java.base does not "opens java.io" to unnamed module

Moving to felix-parent 9 removes ianal but pins maven-antrun-plugin 3.1.0, which
rejects the legacy tasks element:

    You are using 'tasks' which has been removed from the maven-antrun-plugin

Both antrun executions now use target instead.

main has no code change, so its version stays at 7.1.0-SNAPSHOT. The step runs after
the framework step, which installs the framework it embeds.

Verified on JDK 25: main builds, the jar embeds the framework, and launching it
starts the framework and keeps running, with no Security Manager error. The only
output is the known sun.misc.Unsafe warning from URLHandlers.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…uild output

main bundles the framework, so shipping main 7.1.0 containing framework 8.0.0 would
be misleading. Its version moves to 8.0.0-SNAPSHOT alongside the framework.

main.distribution is unaffected: it pins framework.version to the released 7.0.5 and
consumes published artifacts rather than this build.

Also removes six jars totalling 1.7 MB that were committed by mistake in the previous
commit. main/bundle is populated by the build, is not tracked on master, and was not
ignored, so a plain add picked it up. main/bundle, main/bin and main/conf are now in
.gitignore, all three being build output of this module.

Verified on JDK 25: main builds at 8.0.0-SNAPSHOT and the build no longer leaves
untracked artifacts behind.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
main.distribution copies bundles into its basedir the same way main does, so building
it leaves untracked jars behind in bundle/ and bin/. Both are now ignored.

main.distribution/conf is tracked and is deliberately not ignored.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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.

9 participants