Skip to content

fix: make DynaLoader::bootstrap delegate to XSLoader::load fallback chain#493

Merged
fglock merged 1 commit intomasterfrom
fix/dynaloader-bootstrap-fallback
Apr 12, 2026
Merged

fix: make DynaLoader::bootstrap delegate to XSLoader::load fallback chain#493
fglock merged 1 commit intomasterfrom
fix/dynaloader-bootstrap-fallback

Conversation

@fglock
Copy link
Copy Markdown
Owner

@fglock fglock commented Apr 12, 2026

Summary

DynaLoader::bootstrap() previously always died with "Can't load module", making all DynaLoader-based XS modules fail immediately at load time. This prevented modules like Image::Magick, Tk, and others that use DynaLoader instead of XSLoader from loading at all.

Meanwhile, XSLoader::load() already had a sophisticated multi-stage fallback:

  1. Java XS class found → initialize and return true
  2. @ISA has functional parent → return true (inheritance fallback)
  3. ::PP companion loaded → return true
  4. die with "Can't load loadable object..." (matches /loadable object/ pattern for CPAN fallback detection)

Changes

  • DynaLoader.java: delegate bootstrap() to XSLoader.load() instead of unconditionally dying
  • DynaLoader.pm: Perl-side fallback also delegates to XSLoader::load
  • ImageMagick.java: stub Java class with no-op UNLOAD() and constant() so Image::Magick loads cleanly

Before / After

Before After
use Image::Magick Dies: "Can't load module Image::Magick" Succeeds
Image::Magick->new N/A (can't load) Creates object
eval { require Image::Magick } Sets $@, module unusable Succeeds, $@ empty
Error message pattern "Can't load module" (non-standard) "Can't load loadable object..." (matches CPAN fallback pattern)

Impact

This fix improves CPAN compatibility broadly — any module using DynaLoader instead of XSLoader now gets the same fallback behavior. The Image::Magick stub specifically enables the module to load and create objects; actual image operations require a future Java backend (e.g., via javax.imageio).

Test plan

  • make passes (all unit tests)
  • use Image::Magick loads without error
  • Image::Magick->new creates objects
  • eval { require Image::Magick } works for optional dependency checks
  • jcpan Image::Magick reports "up to date"
  • jcpan -t Image::Magick tests run (fail on missing backend, not on load)

Generated with Devin

…hain

DynaLoader::bootstrap() previously always died with "Can't load module",
making all DynaLoader-based XS modules (Image::Magick, Tk, etc.) fail
immediately at load time. XSLoader::load() already had a sophisticated
multi-stage fallback (Java class -> @isa parent -> ::PP companion ->
die with detectable error pattern).

Changes:
- DynaLoader.java: delegate bootstrap() to XSLoader.load() instead of
  unconditionally dying
- DynaLoader.pm: Perl-side fallback also delegates to XSLoader::load
- ImageMagick.java: stub Java class with no-op UNLOAD() and constant()
  so Image::Magick loads cleanly and objects can be created

Before: use Image::Magick dies with "Can't load module Image::Magick"
After:  use Image::Magick succeeds; new() creates objects; eval-based
        optional dependency checks work correctly

Generated with [Devin](https://cli.devin.ai/docs)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@fglock fglock force-pushed the fix/dynaloader-bootstrap-fallback branch from 6f8edf8 to 6227163 Compare April 12, 2026 18:40
@fglock fglock merged commit f11a87d into master Apr 12, 2026
2 checks passed
@fglock fglock deleted the fix/dynaloader-bootstrap-fallback branch April 12, 2026 18:43
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.

1 participant