Skip to content

Library.isLoadable() failing unexpectedly #2928

@openaudible

Description

@openaudible

Library.isLoadable() fails when SWT-OS or SWT-Arch manifest entries are missing, with error:

Libraries for platform win32 cannot be loaded because of incompatible environment

This breaks uber JARs (where build tools lose manifest entries during merge) and universal binaries (where a single manifest can't specify multiple architectures).

I am including a proposed a simple fix to clarify the error message and work under these conditions.

To Reproduce

Scenario 1: Uber JAR

  1. Create Maven project with SWT dependency
  2. Build with maven-assembly-plugin without preserving manifest entries:
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-assembly-plugin</artifactId>
    <configuration>
        <descriptorRefs>
            <descriptorRef>jar-with-dependencies</descriptorRef>
        </descriptorRefs>
    </configuration>
</plugin>
  1. Run the resulting JAR (java -jar xyz-jar-with-dependencies.jar)
  2. Application exits with "incompatible environment" error

Scenario 2: Universal Binary

  1. Create macOS universal binary by combining x86_64 and aarch64 libraries with lipo
  2. Package with single manifest (can only specify one SWT-Arch value)
  3. Run on the non-manifest architecture
  4. Application exits with "incompatible environment" error

Expected behavior

The check should:

  • Allow when manifest entries are missing (uber JAR or universal binary scenario)
  • Fail when manifest entries are present but mismatched (actual wrong platform JAR)
  • Provide clear diagnostic message explaining the mismatch

This distinguishes between acceptable scenarios (missing entries) and actual errors (wrong platform).

Environment

  1. Platform:

    • All OS
    • Windows
    • Linux
    • macOS
  2. Additional OS info: Affects all platforms equally

  3. JRE/JDK version: All versions

Version since

PR #2054 and #2026 cc @HeikoKlare
Introduced in commit 360a270 (April 23, 2025) - likely Eclipse 4.33 or later

Workaround

For uber JARs: Configure build tool to preserve manifest entries:

<archive>
    <manifestEntries>
        <SWT-OS>win32</SWT-OS>
        <SWT-Arch>x86_64</SWT-Arch>
    </manifestEntries>
</archive>

For universal binaries: No workaround available (manifest can only contain single architecture)
I've been using universal binaries for Mac for a long time -- as the .classes are identical and it is pretty trivial to use lipo to merge aarch64 and intel.

Proposed Fix

Location: bundles/org.eclipse.swt/Eclipse SWT PI/common/org/eclipse/swt/internal/Library.java lines 214-222

Current code:

String manifestOS = attributes.getValue("SWT-OS");
String manifestArch = attributes.getValue("SWT-Arch");
if (arch.equals(manifestArch) && os.equals(manifestOS)) {
    return true;
}
return false;  // Fails for both missing AND mismatched

Proposed change:

String manifestOS = attributes.getValue("SWT-OS");
String manifestArch = attributes.getValue("SWT-Arch");

// Missing: allow (uber JAR or universal binary)
if (manifestOS == null || manifestArch == null) {
    return true;
}

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

return true;

This 5-line change:

  • Fixes uber JAR and universal binary scenarios
  • Still catches wrong platform JARs (e.g., Linux JAR on Windows)
  • Provides clear diagnostics when actual mismatch detected
  • Maintains security benefit of platform checking

Thank you SWT Team!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions