Skip to content

Avoid compatibility check failure for Uber JARs and Universal Binaries#3082

Open
HeikoKlare wants to merge 1 commit intoeclipse-platform:masterfrom
vi-eclipse:issue-2928
Open

Avoid compatibility check failure for Uber JARs and Universal Binaries#3082
HeikoKlare wants to merge 1 commit intoeclipse-platform:masterfrom
vi-eclipse:issue-2928

Conversation

@HeikoKlare
Copy link
Contributor

When packaging SWT into an Uber Jar or using universal binaries (for multiple architectures), the Jar manifest cannot reference a single OS and/or architecture. As a result, the compatibility check implemented in Library.isLaodable() can never succeed for such a packaging. With those compatibility checks always being executed upon initialization of SWT with a recent change, using such packaging of SWT became difficult or impossible.

This change makes the initialization of SWT not fail in case the JAR manifest is completely lacking the according entries for OS and architecture. This will still make the initialization fail if an OS and/or architecture is specified in the manifest that is incompatible to the current environment, but in case the manifest does not contain such entries, the library will just (try to) boot. The behavior of Platform.isLoadable() is preserved. That method will still return false in case the Manifest does not contain according entries, as this is the long-standing behavior of that method.

Fixes #2928

When packaging SWT into an Uber Jar or using universal binaries (for
multiple architectures), the Jar manifest cannot reference a single OS
and/or architecture. As a result, the compatibility check implemented in
Library.isLaodable() can never succeed for such a packaging. With those
compatibility checks always being executed upon initialization of SWT
with a recent change, using such packaging of SWT became difficult or
impossible.

This change makes the initialization of SWT not fail in case the JAR
manifest is completely lacking the according entries for OS and
architecture. This will still make the initialization fail if an OS
and/or architecture is specified in the manifest that is incompatible to
the current environment, but in case the manifest does not contain such
entries, the library will just (try to) boot. The behavior of
Platform.isLoadable() is preserved. That method will still return false
in case the Manifest does not contain according entries, as this is the
long-standing behavior of that method.

Fixes eclipse-platform#2928
@github-actions
Copy link
Contributor

Test Results

  176 files  ±0    176 suites  ±0   26m 46s ⏱️ - 3m 39s
4 694 tests ±0  4 672 ✅ ±0  22 💤 ±0  0 ❌ ±0 
  489 runs  ±0    483 ✅ ±0   6 💤 ±0  0 ❌ ±0 

Results for commit 28eecf2. ± Comparison against base commit 588e560.

@HeikoKlare HeikoKlare marked this pull request as ready for review February 14, 2026 11:01
@HeikoKlare
Copy link
Contributor Author

@openaudible would this solution be fine for you?

Copy link

@openaudible openaudible left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would say it might do the trick, but you've introduced complexity and the default isLoadable will still return false negatives.

In my opinion:

  • isLoadable is simply a way for exitIfNotLoadable to catch the case where a developer or user tries to launch SWT code with the wrong jar.
  • Thus, isLoadable should provide a detailed error message right before System.exit is called.
  • isLoadable should not return false unless it is guaranteed to be not loadable. (No false negatives!)
  • loadLibrary failing with one or more error messages has been the real long-standing behavior of SWT. The manifest check was introduced last year.

This function accomplishes the above and doesn't require changes to each Platform. It gives a highly detailed error message which should make it clear exactly which jar is causing the problem and what the architecture mismatch is.

    static boolean isLoadable() {
        URL url = Platform.class.getClassLoader().getResource("org/eclipse/swt/internal/Library.class"); //$NON-NLS-1$
        if (!url.getProtocol().equals("jar")) { //$NON-NLS-1$
            /* SWT is presumably running in a development environment */
            return true;
        }

        String jarPath = null;
        Attributes attributes = null;
        try {
            URLConnection connection = url.openConnection();
            if (!(connection instanceof JarURLConnection jc)) {
                /* should never happen for a "jar:" url */
                return false;
            }
            attributes = jc.getMainAttributes();
            jarPath = jc.getJarFileURL().getPath();
        } catch (IOException e) {
            /* should never happen for a valid SWT jar with the expected manifest values */
            return false;
        }

        String manifestOS = attributes.getValue("SWT-OS"); //$NON-NLS-1$
        String manifestArch = attributes.getValue("SWT-Arch"); //$NON-NLS-1$

        // Missing: allow (uber JAR or universal binary) where manifest entries are stripped
        if (manifestOS == null || manifestArch == null) {
            return true;
        }
        String os = os();
        String arch = arch();

        // Present but mismatched: fail with clear diagnostic
        if (!arch.equals(manifestArch) || !os.equals(manifestOS)) {
            System.err.println("org.eclipse.swt platform mismatch for jar: " + jarPath);
            System.err.println("  Manifest: SWT-OS=" + manifestOS + ", SWT-Arch=" + manifestArch);
            System.err.println("  Runtime: os=" + os + ", arch=" + arch);
            return false;
        }

        return true;
    }

Respectfully,

@HeikoKlare
Copy link
Contributor Author

In general, I share your opinion on the expectation of when Library.isLoadable() should return true/false. However, this is exposed as public API (via SWT.isLoadable()), and we would have to throughly think about changes in behavior of an API method which has been like that since decades. I have no idea how consumers may have used that method and whether they rely on the current behavior, so changing the behavior at least has some risk of breaking consumers. Quite the contrary, no one has complained so far that SWT.isLoadable() returns an unexpected result.

In case we agree that changing the behavior of Library/SWT.isLoadable() is reasonable, it's nothing for the upcoming release anymore (we are beyond M3).

@openaudible
Copy link

If you're happy with it, then it's fine with me.
Thanks for resolving.

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.

Library.isLoadable() failing unexpectedly

2 participants