Re: F41 Change Proposal: Drop Mandatory Requires on JRE (system-wide)
Replying to some previous comments: * OpenJDK 21 is the last version to support Java 8 AFAIK. * Indeed it is possible to compile projects using the system JDK together with the -target + -source / --release flags. * In the spirit of "staying close to the upstream", the our (Maven) ecosystem does not touch the compilation flags unless the project can not be built using the system JDK. In that case we tend to override the selected version to the closest version supported by the system JDK. (See how moving to to OpenJDK 21 required adding these flags in majority of the failing builds.) * I am in favor of adding soft RPM constraints on the Java libraries regarding the bytecode version (like Recommends field) but this move is heavily dependent on what the OpenJDK Provides fields are. I heard there was evolution and some complex reasons why they decided to change the Provides. For this reason, I am not in favor of adding hard constraints (Requires) on Java packages. On 3. 5. 2024 7:44, Christopher wrote: On Thu, May 2, 2024 at 9:24 PM Kevin Kofler via devel wrote: Christopher wrote: So, I actually think that building with the *latest* JDK that we ship, and using the `--release` flag during compilation is actually safer than building against the lowest that we support, because it is most likely to strictly enforce correct byte code generation for the target JRE. The problem is, without ALSO installing the JDK for the targeted version AND explicitly pointing -bootclasspath to that JDK, this does NOT catch code trying to use class library features (as opposed to language or bytecode For context, the use of the bootclasspath is only applicable to building for Java 8. (A related question that I don't know the answer to: how much longer is Fedora going to include Java 8?) However, I believe you are incorrect. JEP 247, which added the `--release` flag, specifically made it replace the need for using `-bootclasspath`. See https://openjdk.org/jeps/247 ; The problem I described in the email you're replying to is specifically that the `-bootclasspath` with JDK 8 will pick up class APIs *outside* of the "", whereas the use of `--release 8` strictly enforces that only the "" are available. This is what I meant when I said that using the `--release` flag more strictly enforces Java 8 language compliance than building with JDK 8. I stand by that statement. It is the `-bootclasspath` that leads people astray, and thus it has been removed for Java 9 and later. features) from the newer JDK, and worse, in rare occasions, even if the source code is in principle compatible with the targeted older Java, when compiled with a newer compiler and older target release, it will fail to actually run (!) with the latter (because the compiler picks up a subclass override of a method added in the newer Java instead of the baseclass method that was always available and, for performance reasons, tries calling the override explicitly rather than going through the virtual method lookup). One example of that latter issue is NetBeans, where versions 12.5 and 12.6 were supposed to be compatible with Java 8, but some upstream-published binaries of 12.5 and all of 12.6 do not actually work properly on it because they were built with Java 11 in "-release 8" mode: some editor features fail with runtime exceptions. See https://issues.apache.org/jira/browse/NETBEANS-6349 for details. (They "fixed" it by just requiring Java 11 in NetBeans 13 and newer. No fixed 12.x release was ever issued.) The CharBuffer/ByteBuffer issues mentioned in that are specifically issues that the use of `--release` resolves. I have fixed this in several projects already who encountered this same issue. Digging into the tickets you linked, it looks like the problem with that issue was that the binaries were built with JDK 11 *without* the use of the `--release` flag... or rather, it looks like somebody tried to use the `--release` flag, but they also used `-Xbootclasspath`, which ended up *disabling* the `--release` behavior. The problem isn't the use of `--release`, it's the *non*-use of it... or the broken use of it, because boot class path options are still being used when they shouldn't. So again, I assert that it's the `-bootclasspath` option that is leading people astray. So I am AGAINST systematically using "-release" without "-bootclasspath", even though that works in most cases and is often successfully used in production (me and my employer use it, too, but on projects we control where we will fix the source code or add a workaround to it if any issues come up from that, not systematically on repackaging third-party projects). The compiler even warns about the missing "-bootclasspath". And the potential to cause subtle misbehavior that is a pain to debug is just too high, especially if we have the actual older JDK available and could just BuildRequire the correct version. This doesn't make sense. The purpose of the `--release` flag was to repl
Re: F41 Change Proposal: Drop Mandatory Requires on JRE (system-wide)
On Thu, May 2, 2024 at 9:24 PM Kevin Kofler via devel wrote: > > Christopher wrote: > > So, I actually think that building with the *latest* JDK that we ship, > > and using the `--release` flag during compilation is actually safer > > than building against the lowest that we support, because it is most > > likely to strictly enforce correct byte code generation for the target > > JRE. > > The problem is, without ALSO installing the JDK for the targeted version AND > explicitly pointing -bootclasspath to that JDK, this does NOT catch code > trying to use class library features (as opposed to language or bytecode For context, the use of the bootclasspath is only applicable to building for Java 8. (A related question that I don't know the answer to: how much longer is Fedora going to include Java 8?) However, I believe you are incorrect. JEP 247, which added the `--release` flag, specifically made it replace the need for using `-bootclasspath`. See https://openjdk.org/jeps/247 ; The problem I described in the email you're replying to is specifically that the `-bootclasspath` with JDK 8 will pick up class APIs *outside* of the "", whereas the use of `--release 8` strictly enforces that only the "" are available. This is what I meant when I said that using the `--release` flag more strictly enforces Java 8 language compliance than building with JDK 8. I stand by that statement. It is the `-bootclasspath` that leads people astray, and thus it has been removed for Java 9 and later. > features) from the newer JDK, and worse, in rare occasions, even if the > source code is in principle compatible with the targeted older Java, when > compiled with a newer compiler and older target release, it will fail to > actually run (!) with the latter (because the compiler picks up a subclass > override of a method added in the newer Java instead of the baseclass method > that was always available and, for performance reasons, tries calling the > override explicitly rather than going through the virtual method lookup). > One example of that latter issue is NetBeans, where versions 12.5 and 12.6 > were supposed to be compatible with Java 8, but some upstream-published > binaries of 12.5 and all of 12.6 do not actually work properly on it because > they were built with Java 11 in "-release 8" mode: some editor features fail > with runtime exceptions. See > https://issues.apache.org/jira/browse/NETBEANS-6349 for details. (They > "fixed" it by just requiring Java 11 in NetBeans 13 and newer. No fixed 12.x > release was ever issued.) The CharBuffer/ByteBuffer issues mentioned in that are specifically issues that the use of `--release` resolves. I have fixed this in several projects already who encountered this same issue. Digging into the tickets you linked, it looks like the problem with that issue was that the binaries were built with JDK 11 *without* the use of the `--release` flag... or rather, it looks like somebody tried to use the `--release` flag, but they also used `-Xbootclasspath`, which ended up *disabling* the `--release` behavior. The problem isn't the use of `--release`, it's the *non*-use of it... or the broken use of it, because boot class path options are still being used when they shouldn't. So again, I assert that it's the `-bootclasspath` option that is leading people astray. > > So I am AGAINST systematically using "-release" without "-bootclasspath", > even though that works in most cases and is often successfully used in > production (me and my employer use it, too, but on projects we control where > we will fix the source code or add a workaround to it if any issues come up > from that, not systematically on repackaging third-party projects). The > compiler even warns about the missing "-bootclasspath". And the potential to > cause subtle misbehavior that is a pain to debug is just too high, > especially if we have the actual older JDK available and could just > BuildRequire the correct version. This doesn't make sense. The purpose of the `--release` flag was to replace the need for `-bootclasspath`. The `-bootclasspath` doesn't exist anymore for JDK 9 compliance and later, and using it *breaks* the compliance checks done by `--release` by allowing the built-in checks to be overridden. As for the warning you've mentioned... I'm not sure what warning you're referring to. I've never seen such a warning and have been using `--release` for a long time now. Respectfully, I think you're wrong on some of the points you're raising. Please look into the points I've made, and correct me if it turns out that I'm the one in error. Getting this correct is important to me, and I think it matters for Fedora's Java packaging guidelines, even if it doesn't end up affecting the decision about Requires. So, I'd like to know if I'm wrong. > > Kevin Kofler > -- > ___ > devel mailing list -- devel@lists.fedoraproject.org > To unsubscribe send an email to devel-le...@li
Re: F41 Change Proposal: Drop Mandatory Requires on JRE (system-wide)
Sorry, with "package" I mean a *new* package for jdk 17, depending on a lib built and tested only for jdk 8 to 11. Basically, that metadata in the rpm for the lib would not have that runtime information for any new package wanting to depend on it targeted for jdk 17. On 5/2/24 18:35, Kevin Kofler via devel wrote: Carlos Rodriguez-Fernandez wrote: How could that be expressed so that those are caught quickly at build time? Someone wants to depend on a java lib that has been tested only in JRE 8 to 11, but wants to build the package with JRE 17+, or vice-versa, for example. Perhaps, the only feasible way to detect that case is with CI. IMHO, the library should have a: Requires: (java-devel >= 1:8 with java-devel < 1:11) Sure, this will not per se prevent you from attempting to use the library with the Java 17 compiler, but if you do not have Java 8 or 11 installed, installing the library attempting to install it as a dependency should raise a red flag. As a quick check, you could write a specfile for your application with: BuildRequires: java-devel >= 1:17 BuildConflicts: java-devel < 1:17 and then run mock on that. The latter line should prevent the old version from being installed in parallel. One annoyance is that older OpenJDK packages currently drop that virtual Provides, presumably in an attempt to get all Java packages systematically built with a newer JDK. That is something that ought to get fixed. (If we switch to building with the oldest possible Java as I suggest, it will have to get fixed anyway.) As is, you may need to explicitly: BuildConflicts: java-1.8.0-devel BuildConflicts: java-11-devel Kevin Kofler -- ___ devel mailing list -- devel@lists.fedoraproject.org To unsubscribe send an email to devel-le...@lists.fedoraproject.org Fedora Code of Conduct: https://docs.fedoraproject.org/en-US/project/code-of-conduct/ List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines List Archives: https://lists.fedoraproject.org/archives/list/devel@lists.fedoraproject.org Do not reply to spam, report it: https://pagure.io/fedora-infrastructure/new_issue OpenPGP_signature.asc Description: OpenPGP digital signature -- ___ devel mailing list -- devel@lists.fedoraproject.org To unsubscribe send an email to devel-le...@lists.fedoraproject.org Fedora Code of Conduct: https://docs.fedoraproject.org/en-US/project/code-of-conduct/ List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines List Archives: https://lists.fedoraproject.org/archives/list/devel@lists.fedoraproject.org Do not reply to spam, report it: https://pagure.io/fedora-infrastructure/new_issue
Re: F41 Change Proposal: Drop Mandatory Requires on JRE (system-wide)
Carlos Rodriguez-Fernandez wrote: > How could that be expressed so that those are caught quickly at build > time? Someone wants to depend on a java lib that has been tested only in > JRE 8 to 11, but wants to build the package with JRE 17+, or vice-versa, > for example. Perhaps, the only feasible way to detect that case is with > CI. IMHO, the library should have a: Requires: (java-devel >= 1:8 with java-devel < 1:11) Sure, this will not per se prevent you from attempting to use the library with the Java 17 compiler, but if you do not have Java 8 or 11 installed, installing the library attempting to install it as a dependency should raise a red flag. As a quick check, you could write a specfile for your application with: BuildRequires: java-devel >= 1:17 BuildConflicts: java-devel < 1:17 and then run mock on that. The latter line should prevent the old version from being installed in parallel. One annoyance is that older OpenJDK packages currently drop that virtual Provides, presumably in an attempt to get all Java packages systematically built with a newer JDK. That is something that ought to get fixed. (If we switch to building with the oldest possible Java as I suggest, it will have to get fixed anyway.) As is, you may need to explicitly: BuildConflicts: java-1.8.0-devel BuildConflicts: java-11-devel Kevin Kofler -- ___ devel mailing list -- devel@lists.fedoraproject.org To unsubscribe send an email to devel-le...@lists.fedoraproject.org Fedora Code of Conduct: https://docs.fedoraproject.org/en-US/project/code-of-conduct/ List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines List Archives: https://lists.fedoraproject.org/archives/list/devel@lists.fedoraproject.org Do not reply to spam, report it: https://pagure.io/fedora-infrastructure/new_issue
Re: F41 Change Proposal: Drop Mandatory Requires on JRE (system-wide)
Christopher wrote: > So, I actually think that building with the *latest* JDK that we ship, > and using the `--release` flag during compilation is actually safer > than building against the lowest that we support, because it is most > likely to strictly enforce correct byte code generation for the target > JRE. The problem is, without ALSO installing the JDK for the targeted version AND explicitly pointing -bootclasspath to that JDK, this does NOT catch code trying to use class library features (as opposed to language or bytecode features) from the newer JDK, and worse, in rare occasions, even if the source code is in principle compatible with the targeted older Java, when compiled with a newer compiler and older target release, it will fail to actually run (!) with the latter (because the compiler picks up a subclass override of a method added in the newer Java instead of the baseclass method that was always available and, for performance reasons, tries calling the override explicitly rather than going through the virtual method lookup). One example of that latter issue is NetBeans, where versions 12.5 and 12.6 were supposed to be compatible with Java 8, but some upstream-published binaries of 12.5 and all of 12.6 do not actually work properly on it because they were built with Java 11 in "-release 8" mode: some editor features fail with runtime exceptions. See https://issues.apache.org/jira/browse/NETBEANS-6349 for details. (They "fixed" it by just requiring Java 11 in NetBeans 13 and newer. No fixed 12.x release was ever issued.) So I am AGAINST systematically using "-release" without "-bootclasspath", even though that works in most cases and is often successfully used in production (me and my employer use it, too, but on projects we control where we will fix the source code or add a workaround to it if any issues come up from that, not systematically on repackaging third-party projects). The compiler even warns about the missing "-bootclasspath". And the potential to cause subtle misbehavior that is a pain to debug is just too high, especially if we have the actual older JDK available and could just BuildRequire the correct version. Kevin Kofler -- ___ devel mailing list -- devel@lists.fedoraproject.org To unsubscribe send an email to devel-le...@lists.fedoraproject.org Fedora Code of Conduct: https://docs.fedoraproject.org/en-US/project/code-of-conduct/ List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines List Archives: https://lists.fedoraproject.org/archives/list/devel@lists.fedoraproject.org Do not reply to spam, report it: https://pagure.io/fedora-infrastructure/new_issue
Re: F41 Change Proposal: Drop Mandatory Requires on JRE (system-wide)
I have dealt with bugs where a library runs well in JRE 11, but crashes when run in JRE 17 because the InetSocketAddress implementation changed. Totally unrelated with the language features or bytecode versions. Nevertheless, even in that case, if I bring in that library from the distro repo, I wouldn't want that lib to also bring JRE 11, because I'll be running my app in JRE 17, however, ... I'd learn quickly that it fails. The other way around can happen too, a library runs well in 17, but crashes in JRE 11 because of that InetSocketAddress change, for example. How could that be expressed so that those are caught quickly at build time? Someone wants to depend on a java lib that has been tested only in JRE 8 to 11, but wants to build the package with JRE 17+, or vice-versa, for example. Perhaps, the only feasible way to detect that case is with CI. On 5/2/24 11:58, Christopher wrote: On Thu, May 2, 2024 at 6:59 AM Kevin Kofler via devel wrote: Carlos Rodriguez-Fernandez wrote: Regarding the proposal as a whole, I think the proposal idea makes a lot of sense, but for apps depending on system jar libraries, there should be a way to specify that the app depends on a specific java bytecode version range. System libraries packages could provide compatibility packages, so couldn't those apps just depend on those compatibility packages instead? That can become a maintenance burden for those libs, though. The safest approach for library JARs would be to always build them against the lowest possible Java version (the oldest JDK branch that we still ship if the library supports that, otherwise the oldest the library supports). And IMHO, if the library is built against a higher version than the lowest we ship, it needs a versioned Requires on the JRE. Kevin Kofler I have noticed that the `--release` flag on javac (JDK>=9) actually enforces JLS compliance more strictly than even compiling with the specific version it targets. For example, it is possible to write a project that is non-compliant with the Java 8 JLS that the Java 8 compiler will incorrectly permit without error. Such a project will not work properly on Java 9 and newer JREs. However, if JDK 9 were used to compile the project with `javac --release 8`, the compiler will catch the non-compliance with the Java 8 JLS that the JDK 8 compiler failed to catch, forcing compliance with Java 8, and allowing the resulting byte code to work on JRE 9 and later. So, I actually think that building with the *latest* JDK that we ship, and using the `--release` flag during compilation is actually safer than building against the lowest that we support, because it is most likely to strictly enforce correct byte code generation for the target JRE. But, this requires project maintainers to explicitly add the use of the `--release` flag if the upstream build does not already set it in some way. Doing this, it should not matter which of our JDKs it builds with, but building with the latest available (rather than the oldest available, as Kevin suggests) will have the best chance for compliance-related bugs to be fixed (but only if the `--release` flag is used). Of course, there are many ways to break Java libraries across JRE versions, but the one I'm focusing on here is one that is preventable, due to JDK enforcement of JLS compliance during compilation, which is more strict in newer JDKs than in earlier ones. If upstream's oldest supported JRE is still supported by the `--release` flag by the JDK used in Fedora's build, then it should be fine to just specify that version, even if it is older than the oldest JRE that Fedora ships. In such cases, it might not technically be necessary to specify a Requires for the JRE. However, if the oldest supported JRE in the upstream project is newer than Fedora's oldest shipped JRE, then having the Requires >= would still be needed. For example, if Fedora ships JRE 11, 17, and 21, and the upstream project targets Java 8, then it should be fine to build that project using JDK 21 with `--release 8` and have no Requires. However, if upstream targets Java 11, then building using JDK 21 with `--release 11` would be okay, but you'd need Requires >= 11 (or maybe Recommends >= 11 ?). I don't object to the original proposal, though. There have been times I've wanted to install a Java library not to run it, but to inspect the jar with a third-party tool (or even just vim). But, I think it's important for Java package maintainers to be aware of what versions their packages' upstream projects are targeting, and make sure they are built correctly for Fedora using Fedora's JDKs. I also think it's important that Fedora packagers communicate the JRE requirements for each package *if* it were to be run. Maybe that can be done with Recommends instead of Requires? I'm not sure about that part, but I acknowledge that installing a library is not the same as intending for it to be run. Christopher -- ___
Re: F41 Change Proposal: Drop Mandatory Requires on JRE (system-wide)
On Thu, May 2, 2024 at 6:59 AM Kevin Kofler via devel wrote: > > Carlos Rodriguez-Fernandez wrote: > > Regarding the proposal as a whole, I think the proposal idea makes a lot > > of sense, but for apps depending on system jar libraries, there should > > be a way to specify that the app depends on a specific java bytecode > > version range. System libraries packages could provide compatibility > > packages, so couldn't those apps just depend on those compatibility > > packages instead? That can become a maintenance burden for those libs, > > though. > > The safest approach for library JARs would be to always build them against > the lowest possible Java version (the oldest JDK branch that we still ship > if the library supports that, otherwise the oldest the library supports). > And IMHO, if the library is built against a higher version than the lowest > we ship, it needs a versioned Requires on the JRE. > > Kevin Kofler I have noticed that the `--release` flag on javac (JDK>=9) actually enforces JLS compliance more strictly than even compiling with the specific version it targets. For example, it is possible to write a project that is non-compliant with the Java 8 JLS that the Java 8 compiler will incorrectly permit without error. Such a project will not work properly on Java 9 and newer JREs. However, if JDK 9 were used to compile the project with `javac --release 8`, the compiler will catch the non-compliance with the Java 8 JLS that the JDK 8 compiler failed to catch, forcing compliance with Java 8, and allowing the resulting byte code to work on JRE 9 and later. So, I actually think that building with the *latest* JDK that we ship, and using the `--release` flag during compilation is actually safer than building against the lowest that we support, because it is most likely to strictly enforce correct byte code generation for the target JRE. But, this requires project maintainers to explicitly add the use of the `--release` flag if the upstream build does not already set it in some way. Doing this, it should not matter which of our JDKs it builds with, but building with the latest available (rather than the oldest available, as Kevin suggests) will have the best chance for compliance-related bugs to be fixed (but only if the `--release` flag is used). Of course, there are many ways to break Java libraries across JRE versions, but the one I'm focusing on here is one that is preventable, due to JDK enforcement of JLS compliance during compilation, which is more strict in newer JDKs than in earlier ones. If upstream's oldest supported JRE is still supported by the `--release` flag by the JDK used in Fedora's build, then it should be fine to just specify that version, even if it is older than the oldest JRE that Fedora ships. In such cases, it might not technically be necessary to specify a Requires for the JRE. However, if the oldest supported JRE in the upstream project is newer than Fedora's oldest shipped JRE, then having the Requires >= would still be needed. For example, if Fedora ships JRE 11, 17, and 21, and the upstream project targets Java 8, then it should be fine to build that project using JDK 21 with `--release 8` and have no Requires. However, if upstream targets Java 11, then building using JDK 21 with `--release 11` would be okay, but you'd need Requires >= 11 (or maybe Recommends >= 11 ?). I don't object to the original proposal, though. There have been times I've wanted to install a Java library not to run it, but to inspect the jar with a third-party tool (or even just vim). But, I think it's important for Java package maintainers to be aware of what versions their packages' upstream projects are targeting, and make sure they are built correctly for Fedora using Fedora's JDKs. I also think it's important that Fedora packagers communicate the JRE requirements for each package *if* it were to be run. Maybe that can be done with Recommends instead of Requires? I'm not sure about that part, but I acknowledge that installing a library is not the same as intending for it to be run. Christopher -- ___ devel mailing list -- devel@lists.fedoraproject.org To unsubscribe send an email to devel-le...@lists.fedoraproject.org Fedora Code of Conduct: https://docs.fedoraproject.org/en-US/project/code-of-conduct/ List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines List Archives: https://lists.fedoraproject.org/archives/list/devel@lists.fedoraproject.org Do not reply to spam, report it: https://pagure.io/fedora-infrastructure/new_issue
Re: F41 Change Proposal: Drop Mandatory Requires on JRE (system-wide)
Carlos Rodriguez-Fernandez wrote: > Regarding the proposal as a whole, I think the proposal idea makes a lot > of sense, but for apps depending on system jar libraries, there should > be a way to specify that the app depends on a specific java bytecode > version range. System libraries packages could provide compatibility > packages, so couldn't those apps just depend on those compatibility > packages instead? That can become a maintenance burden for those libs, > though. The safest approach for library JARs would be to always build them against the lowest possible Java version (the oldest JDK branch that we still ship if the library supports that, otherwise the oldest the library supports). And IMHO, if the library is built against a higher version than the lowest we ship, it needs a versioned Requires on the JRE. Kevin Kofler -- ___ devel mailing list -- devel@lists.fedoraproject.org To unsubscribe send an email to devel-le...@lists.fedoraproject.org Fedora Code of Conduct: https://docs.fedoraproject.org/en-US/project/code-of-conduct/ List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines List Archives: https://lists.fedoraproject.org/archives/list/devel@lists.fedoraproject.org Do not reply to spam, report it: https://pagure.io/fedora-infrastructure/new_issue
Re: F41 Change Proposal: Drop Mandatory Requires on JRE (system-wide)
Marián, I echo your concerns, however, regarding jars with multiple bytecode versions, aren't java rpm expected to build their sources with one specific JDK? (per the guidelines) how can multiple bytecode version end up in the JAR in that scenario? Regarding the proposal as a whole, I think the proposal idea makes a lot of sense, but for apps depending on system jar libraries, there should be a way to specify that the app depends on a specific java bytecode version range. System libraries packages could provide compatibility packages, so couldn't those apps just depend on those compatibility packages instead? That can become a maintenance burden for those libs, though. Thank you, Carlos. On 4/30/24 07:56, Marián Konček wrote: On 25. 4. 2024 17:46, Michel Lind wrote: On 4/24/24 11:14 AM, Aoife Moloney wrote: Wiki - https://fedoraproject.org/wiki/Changes/Drop_Mandatory_Requires_on_JRE Announced - https://discussion.fedoraproject.org/t/f41-change-proposal-drop-mandatory-requires-on-jre-system-wide/114186 [snip] === Context === Java packages are compiled using `javac` into `.class` files and composed into `.jar` archives. Jar archives can be used as compile or runtime dependencies for other packages or can be directly executed with the java command provided by a JRE. Jar archives can be executed using the command: `java -jar ${FILE}`. This command executes the `main` method either specified via CLI or specified within the Jar manifest file. Java packages, which serve as libraries only, lack the `main` method and are not executable. Therefore, there is no requirement on any specific JRE imposed by the library implicitly. Sort of... bytecodes do get introduced over time, right? While in practice I expect nobody will try and running, say, anything older than Java 7 (JSR 7 introduced invokedynamic), should there be a way to specify a generic minimum runtime version? I guess the tricky thing here is that different JDKs might not be packaged in a way where they all implement a common virtual provide that can be targeted $ fedrq pkgs -P java-headless java-21-openjdk-headless-1:21.0.2.0.13-3.fc41.x86_64 $ fedrq pkgs -P java-headless -F provides libjsvml.so()(64bit) libsyslookup.so()(64bit) libjvm.so()(64bit) libjvm.so(SUNWprivate_1.1)(64bit) lible.so()(64bit) libjava.so()(64bit) libjsig.so()(64bit) libverify.so()(64bit) java-21-openjdk-headless(x86-64) = 1:21.0.2.0.13-3.fc41 config(java-21-openjdk-headless) = 1:21.0.2.0.13-3.fc41 java-21-headless = 1:21.0.2.0.13-3.fc41 java-21-openjdk-headless = 1:21.0.2.0.13-3.fc41 java-headless = 1:21.0.2.0.13-3.fc41 java-openjdk-headless = 1:21.0.2.0.13-3.fc41 jre-21-headless = 1:21.0.2.0.13-3.fc41 jre-21-openjdk-headless = 1:21.0.2.0.13-3.fc41 jre-headless = 1:21.0.2.0.13-3.fc41 jre-openjdk-headless = 1:21.0.2.0.13-3.fc41 Every major JDK version introduces a new bytecode version. The bytecode version number is part of the .class file format. If an older JVM is attempting to load a .class with a higher bytecode version than it supports, it fails without attempting to load it. What you propose makes some sense but I am not completely convinced it is a good idea. First of all we need to agree on the meaning of the Requires field and what it means to install a package. * Does one install a package just to look at the files / contents / bytecode of the classes? In that case there is no strict requirement on the bytecode interpreter (= JVM). * Does one install a package to **use** it? To load the bytecode using some JVM? In that case adding a requirement to the package turns a runtime failure (to load the class) into an RPM transaction. Even if we would agree on the second option, there is another problem: an .rpm archive can contain multiple .jar files. a .jar archive consists of multiple .class files. Bytecode version is specified for each .class file. While a generator that walks over the whole contents and extracts the bytecode version numbers could be implemented, should it simply reduce the numbers to a maximum? That would possibly prevent the users from some valid use cases. Should the packaging guidelines specify that an .rpm package may install at most one .jar archive? Although rare, there are cases when even .class files in a single .jar have different versions. Most notable case: module-info.jar with bytecode version for Java 9 and the rest of the source files with version for Java < 9. Looking at it, I see many questions and potential problems but I also find this idea intriguing, to have a generated `Requires: java-bytecode >= 55` or something like that. This would also require all the JVMs to Provide such a field. The spirit of this proposal, however, is to allow more freedom for the package users at the cost of disabling some implicit behaviours. === Different JDKs === This proposal is also related to the topic of different JDKs. Developers may want to use or build packages
Re: F41 Change Proposal: Drop Mandatory Requires on JRE (system-wide)
On 25. 4. 2024 17:46, Michel Lind wrote: On 4/24/24 11:14 AM, Aoife Moloney wrote: Wiki - https://fedoraproject.org/wiki/Changes/Drop_Mandatory_Requires_on_JRE Announced - https://discussion.fedoraproject.org/t/f41-change-proposal-drop-mandatory-requires-on-jre-system-wide/114186 [snip] === Context === Java packages are compiled using `javac` into `.class` files and composed into `.jar` archives. Jar archives can be used as compile or runtime dependencies for other packages or can be directly executed with the java command provided by a JRE. Jar archives can be executed using the command: `java -jar ${FILE}`. This command executes the `main` method either specified via CLI or specified within the Jar manifest file. Java packages, which serve as libraries only, lack the `main` method and are not executable. Therefore, there is no requirement on any specific JRE imposed by the library implicitly. Sort of... bytecodes do get introduced over time, right? While in practice I expect nobody will try and running, say, anything older than Java 7 (JSR 7 introduced invokedynamic), should there be a way to specify a generic minimum runtime version? I guess the tricky thing here is that different JDKs might not be packaged in a way where they all implement a common virtual provide that can be targeted $ fedrq pkgs -P java-headless java-21-openjdk-headless-1:21.0.2.0.13-3.fc41.x86_64 $ fedrq pkgs -P java-headless -F provides libjsvml.so()(64bit) libsyslookup.so()(64bit) libjvm.so()(64bit) libjvm.so(SUNWprivate_1.1)(64bit) lible.so()(64bit) libjava.so()(64bit) libjsig.so()(64bit) libverify.so()(64bit) java-21-openjdk-headless(x86-64) = 1:21.0.2.0.13-3.fc41 config(java-21-openjdk-headless) = 1:21.0.2.0.13-3.fc41 java-21-headless = 1:21.0.2.0.13-3.fc41 java-21-openjdk-headless = 1:21.0.2.0.13-3.fc41 java-headless = 1:21.0.2.0.13-3.fc41 java-openjdk-headless = 1:21.0.2.0.13-3.fc41 jre-21-headless = 1:21.0.2.0.13-3.fc41 jre-21-openjdk-headless = 1:21.0.2.0.13-3.fc41 jre-headless = 1:21.0.2.0.13-3.fc41 jre-openjdk-headless = 1:21.0.2.0.13-3.fc41 Every major JDK version introduces a new bytecode version. The bytecode version number is part of the .class file format. If an older JVM is attempting to load a .class with a higher bytecode version than it supports, it fails without attempting to load it. What you propose makes some sense but I am not completely convinced it is a good idea. First of all we need to agree on the meaning of the Requires field and what it means to install a package. * Does one install a package just to look at the files / contents / bytecode of the classes? In that case there is no strict requirement on the bytecode interpreter (= JVM). * Does one install a package to **use** it? To load the bytecode using some JVM? In that case adding a requirement to the package turns a runtime failure (to load the class) into an RPM transaction. Even if we would agree on the second option, there is another problem: an .rpm archive can contain multiple .jar files. a .jar archive consists of multiple .class files. Bytecode version is specified for each .class file. While a generator that walks over the whole contents and extracts the bytecode version numbers could be implemented, should it simply reduce the numbers to a maximum? That would possibly prevent the users from some valid use cases. Should the packaging guidelines specify that an .rpm package may install at most one .jar archive? Although rare, there are cases when even .class files in a single .jar have different versions. Most notable case: module-info.jar with bytecode version for Java 9 and the rest of the source files with version for Java < 9. Looking at it, I see many questions and potential problems but I also find this idea intriguing, to have a generated `Requires: java-bytecode >= 55` or something like that. This would also require all the JVMs to Provide such a field. The spirit of this proposal, however, is to allow more freedom for the package users at the cost of disabling some implicit behaviours. === Different JDKs === This proposal is also related to the topic of different JDKs. Developers may want to use or build packages which use a JDK different than the one provided by the `java--openjdk` package. After this proposal was implemented, they would be able to depend on Java library packages with no introduction of the OpenJDK package. === Rationale === Java libraries are more similar to native libraries than to libraries written in dynamic scripting languages. They are compiled to a bytecode and are not executable. Java libraries can be used as dependencies for any Java application and there is no implicit dependency on the system default JDK. Java applications, on the other hand, are expected to be tested and to work with the system JDK and from the user's perspective: after installing an application they must be able to simply run the binary. Therefore the `Requi
Re: F41 Change Proposal: Drop Mandatory Requires on JRE (system-wide)
On 4/24/24 11:14 AM, Aoife Moloney wrote: Wiki - https://fedoraproject.org/wiki/Changes/Drop_Mandatory_Requires_on_JRE Announced - https://discussion.fedoraproject.org/t/f41-change-proposal-drop-mandatory-requires-on-jre-system-wide/114186 [snip] === Context === Java packages are compiled using `javac` into `.class` files and composed into `.jar` archives. Jar archives can be used as compile or runtime dependencies for other packages or can be directly executed with the java command provided by a JRE. Jar archives can be executed using the command: `java -jar ${FILE}`. This command executes the `main` method either specified via CLI or specified within the Jar manifest file. Java packages, which serve as libraries only, lack the `main` method and are not executable. Therefore, there is no requirement on any specific JRE imposed by the library implicitly. Sort of... bytecodes do get introduced over time, right? While in practice I expect nobody will try and running, say, anything older than Java 7 (JSR 7 introduced invokedynamic), should there be a way to specify a generic minimum runtime version? I guess the tricky thing here is that different JDKs might not be packaged in a way where they all implement a common virtual provide that can be targeted $ fedrq pkgs -P java-headless java-21-openjdk-headless-1:21.0.2.0.13-3.fc41.x86_64 $ fedrq pkgs -P java-headless -F provides libjsvml.so()(64bit) libsyslookup.so()(64bit) libjvm.so()(64bit) libjvm.so(SUNWprivate_1.1)(64bit) lible.so()(64bit) libjava.so()(64bit) libjsig.so()(64bit) libverify.so()(64bit) java-21-openjdk-headless(x86-64) = 1:21.0.2.0.13-3.fc41 config(java-21-openjdk-headless) = 1:21.0.2.0.13-3.fc41 java-21-headless = 1:21.0.2.0.13-3.fc41 java-21-openjdk-headless = 1:21.0.2.0.13-3.fc41 java-headless = 1:21.0.2.0.13-3.fc41 java-openjdk-headless = 1:21.0.2.0.13-3.fc41 jre-21-headless = 1:21.0.2.0.13-3.fc41 jre-21-openjdk-headless = 1:21.0.2.0.13-3.fc41 jre-headless = 1:21.0.2.0.13-3.fc41 jre-openjdk-headless = 1:21.0.2.0.13-3.fc41 === Different JDKs === This proposal is also related to the topic of different JDKs. Developers may want to use or build packages which use a JDK different than the one provided by the `java--openjdk` package. After this proposal was implemented, they would be able to depend on Java library packages with no introduction of the OpenJDK package. === Rationale === Java libraries are more similar to native libraries than to libraries written in dynamic scripting languages. They are compiled to a bytecode and are not executable. Java libraries can be used as dependencies for any Java application and there is no implicit dependency on the system default JDK. Java applications, on the other hand, are expected to be tested and to work with the system JDK and from the user's perspective: after installing an application they must be able to simply run the binary. Therefore the `Requires` on the system JDK is kept for Java applications. Would this be clearer if it says "the JRE from the system JDK"? Since the apps are not actually pulling in the full JDK itself. Best regards, -- _o) Michel Lind _( ) identities: https://keyoxide.org/5dce2e7e9c3b1cffd335c1d78b229d2f7ccc04f2 OpenPGP_0x8B229D2F7CCC04F2.asc Description: OpenPGP public key OpenPGP_signature.asc Description: OpenPGP digital signature -- ___ devel mailing list -- devel@lists.fedoraproject.org To unsubscribe send an email to devel-le...@lists.fedoraproject.org Fedora Code of Conduct: https://docs.fedoraproject.org/en-US/project/code-of-conduct/ List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines List Archives: https://lists.fedoraproject.org/archives/list/devel@lists.fedoraproject.org Do not reply to spam, report it: https://pagure.io/fedora-infrastructure/new_issue
F41 Change Proposal: Drop Mandatory Requires on JRE (system-wide)
Wiki - https://fedoraproject.org/wiki/Changes/Drop_Mandatory_Requires_on_JRE Announced - https://discussion.fedoraproject.org/t/f41-change-proposal-drop-mandatory-requires-on-jre-system-wide/114186 This is a proposed Change for Fedora Linux. This document represents a proposed Change. As part of the Changes process, proposals are publicly announced in order to receive community feedback. This proposal will only be implemented if approved by the Fedora Engineering Steering Committee. == Summary == Drop the requirement of Java libraries to have Requires on JREs. == Owner == * Name: [[User:mkoncek| Marián Konček]] * Email: mkon...@redhat.com == Detailed Description == Current [https://docs.fedoraproject.org/en-US/packaging-guidelines/Java/#_buildrequires_and_requires guidelines] require all Java packages to `Require: java-headless or java-headless >= 1:minimal_required_version`. Our aim is to drop this explicit requirement on Java library packages. The requirement should stay for Java applications. === Context === Java packages are compiled using `javac` into `.class` files and composed into `.jar` archives. Jar archives can be used as compile or runtime dependencies for other packages or can be directly executed with the java command provided by a JRE. Jar archives can be executed using the command: `java -jar ${FILE}`. This command executes the `main` method either specified via CLI or specified within the Jar manifest file. Java packages, which serve as libraries only, lack the `main` method and are not executable. Therefore, there is no requirement on any specific JRE imposed by the library implicitly. === Different JDKs === This proposal is also related to the topic of different JDKs. Developers may want to use or build packages which use a JDK different than the one provided by the `java--openjdk` package. After this proposal was implemented, they would be able to depend on Java library packages with no introduction of the OpenJDK package. === Rationale === Java libraries are more similar to native libraries than to libraries written in dynamic scripting languages. They are compiled to a bytecode and are not executable. Java libraries can be used as dependencies for any Java application and there is no implicit dependency on the system default JDK. Java applications, on the other hand, are expected to be tested and to work with the system JDK and from the user's perspective: after installing an application they must be able to simply run the binary. Therefore the `Requires` on the system JDK is kept for Java applications. == Feedback == == Benefit to Fedora == * Very little user-visible benefit. * Reduced dependencies of Java packages. * Simplified maintenance of Java packages. ** Smaller impact of JDK major updates (e.g. `1.8.0 -> 11 -> 17 -> 21`). Introducing a new system version of JDK requires the rebuild of each Java package in order to have updated `Requires` to contain the newest version. == Scope == * Proposal owners: ** Find all Java applications in Fedora, i.e. packages which `BuildRequire` `java-devel / maven-local / ant` and at the same time install files into `/bin` or `/sbin` or `/usr/bin` or `/usr/sbin`. ** Open pull requests adding `Requires: java-headless` into their `.spec` file. ** Remove `Requires` generator from [https://src.fedoraproject.org/rpms/javapackages-tools/blob/8714cc1d03d3f31251539c3fca53383b822834bc/f/javapackages-config.json#_5 javapackages-tools] ** Wait for a mass rebuild. * Other developers: ** Maintainers of Java applications will need to add an explicit `Requires: java-headless` field into their `.spec` file or a specific version of thereof (such as `java-17-openjdk-headless`). * Release engineering: [https://pagure.io/releng/issue/12069 #12069] ** Mass rebuild is not required, this change can propagate via natural rebuilds. * Policies and guidelines: ** Guidelines need to be modified ([https://pagure.io/packaging-committee/pull-request/1360 open Pull Request]). * Trademark approval: N/A (not needed for this Change) * Alignment with Community Initiatives: N/A == Upgrade/compatibility impact == * For Java libraries: ** This change is removing `Requires` and therefore users manually installing a Java library will not additionally install the JVM. * For Java applications: ** After fully implemented, applications will no longer be installable along with any JVM but rather only the system one (unless the package maintainer decides otherwise) == How To Test == * Installing a Java library should not typically install JVM (but can if the library depends on a Java application) * Installing a Java application MUST cause the installation of the system-wide JVM (or a different version thereof) * Executing a binary installed in typical locations (such as `/usr/bin`) MUST NOT cause an error related to the JVM not being installed. == User Experience == Users with no Java application installed, but some Java libraries installe