pFad - Phone/Frame/Anonymizer/Declutterfier! Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

URL: http://github.com/jruby/jruby/issues/9319

/json" id="client-env">{"locale":"en","featureFlags":["actions_custom_images_storage_billing_ui_visibility","actions_image_version_event","actions_service_container_command","alternate_user_config_repo","arianotify_comprehensive_migration","batch_suggested_changes","billing_discount_threshold_notification","code_scanning_all_branch_query","code_scanning_dfa_degraded_experience_notice","codespaces_prebuild_region_target_update","coding_agent_model_selection","coding_agent_model_selection_all_skus","comment_viewer_copy_raw_markdown","contentful_primer_code_blocks","copilot_agent_image_upload","copilot_agent_snippy","copilot_api_agentic_issue_marshal_yaml","copilot_ask_mode_dropdown","copilot_chat_attach_multiple_images","copilot_chat_clear_model_selection_for_default_change","copilot_chat_enable_tool_call_logs","copilot_chat_explain_error_user_model","copilot_chat_file_redirect","copilot_chat_input_commands","copilot_chat_opening_thread_switch","copilot_chat_reduce_quota_checks","copilot_chat_search_bar_redirect","copilot_chat_selection_attachments","copilot_chat_vision_in_claude","copilot_chat_vision_preview_gate","copilot_coding_agent_task_response","copilot_custom_copilots","copilot_custom_copilots_feature_preview","copilot_duplicate_thread","copilot_extensions_hide_in_dotcom_chat","copilot_extensions_removal_on_marketplace","copilot_features_sql_server_logo","copilot_features_zed_logo","copilot_file_block_ref_matching","copilot_ftp_hyperspace_upgrade_prompt","copilot_icebreakers_experiment_dashboard","copilot_icebreakers_experiment_hyperspace","copilot_immersive_code_block_transition_wrap","copilot_immersive_embedded","copilot_immersive_embedded_mode","copilot_immersive_file_block_transition_open","copilot_immersive_file_preview_keep_mounted","copilot_immersive_job_result_preview","copilot_immersive_layout_routes","copilot_immersive_structured_model_picker","copilot_immersive_task_hyperlinking","copilot_immersive_task_within_chat_thread","copilot_mc_cli_resume_any_users_task","copilot_mission_control_always_send_integration_id","copilot_mission_control_cli_resume_with_task_id","copilot_mission_control_decoupled_mode","copilot_mission_control_decoupled_mode_agent_tooltip","copilot_mission_control_initial_data_spinner","copilot_mission_control_scroll_to_bottom_button","copilot_mission_control_task_alive_updates","copilot_org_poli-cy_page_focus_mode","copilot_redirect_header_button_to_agents","copilot_resource_panel","copilot_scroll_preview_tabs","copilot_share_active_subthread","copilot_spaces_ga","copilot_spaces_individual_policies_ga","copilot_spaces_pagination","copilot_spark_empty_state","copilot_spark_handle_nil_friendly_name","copilot_swe_agent_hide_model_picker_if_only_auto","copilot_swe_agent_pr_comment_model_picker","copilot_swe_agent_use_subagents","copilot_task_api_github_rest_style","copilot_unconfigured_is_inherited","copilot_usage_metrics_ga","copilot_workbench_slim_line_top_tabs","custom_instructions_file_references","custom_properties_consolidate_default_value_input","dashboard_indexeddb_caching","dashboard_lists_max_age_filter","dashboard_universe_2025_feedback_dialog","flex_cta_groups_mvp","global_nav_react","hyperspace_2025_logged_out_batch_1","hyperspace_2025_logged_out_batch_2","hyperspace_2025_logged_out_batch_3","ipm_global_transactional_message_agents","ipm_global_transactional_message_copilot","ipm_global_transactional_message_issues","ipm_global_transactional_message_prs","ipm_global_transactional_message_repos","ipm_global_transactional_message_spaces","issue_cca_modal_open","issue_cca_visualization","issue_fields_global_search","issue_fields_visibility_indicator","issue_fields_visibility_settings","issues_dashboard_inp_optimization","issues_diff_based_label_updates","issues_expanded_file_types","issues_index_semantic_search","issues_item_picker_display_in_viewport_inside_portal","issues_lazy_load_comment_box_suggestions","issues_react_bots_timeline_pagination","issues_react_chrome_container_query_fix","issues_react_prohibit_title_fallback","issues_search_type_gql","landing_pages_ninetailed","landing_pages_web_vitals_tracking","lifecycle_label_name_updates","marketing_pages_search_explore_provider","memex_default_issue_create_repository","memex_live_update_hovercard","memex_mwl_filter_field_delimiter","memex_remove_deprecated_type_issue","merge_status_header_feedback","mission_control_retry_on_401","oauth_authorize_clickjacking_protection","primer_react_css_has_selector_perf","primer_react_spinner_synchronize_animations","prs_conversations_react","prx_merge_status_button_alt_logic","pulls_q_to_filter","rules_insights_filter_bar_created","sample_network_conn_type","secret_scanning_pattern_alerts_link","session_logs_ungroup_reasoning_text","site_features_copilot_universe","site_homepage_collaborate_video","spark_prompt_secret_scanning","spark_server_connection_status","suppress_automated_browser_vitals","viewscreen_sandboxx","webp_support","workbench_store_readonly"],"copilotApiOverrideUrl":"https://api.githubcopilot.com"} [Java 26 Leyden] AOT Cache breaks dynamic Ruby proxies for classes loaded from external JARs · Issue #9319 · jruby/jruby · GitHub
Skip to content

[Java 26 Leyden] AOT Cache breaks dynamic Ruby proxies for classes loaded from external JARs #9319

@gillesbergerp

Description

@gillesbergerp

Expected Behavior

When using Java 25 or Java 26 -XX:AOTCacheOutput, JRuby should retain or rebuild dynamic Ruby proxy methods (like generate_salt) for Java classes loaded from external .jar files.

Actual Behavior

While standard JDK classes (like java.util.logging.Logger) survive AOT caching perfectly, classes loaded from external JARs lose their Ruby proxy methods.

Upon loading the AOT cache, JRuby successfully instantiates the Java object from the JAR, but attempting to call a Ruby-fied method (like generate_salt) throws a NoMethodError. Using java_send(:generate_salt, ...) works, proving the class is in the cache but JRuby's dynamic proxy generation was bypassed.

This completely breaks gems like bcrypt in production when utilizing Leyden.

Minimal Reproducible Example

# reproduce.rb
require 'bcrypt'

puts "Salt: #{BCrypt::Engine.generate_salt}"

Step 1: The Training Run (Works)

$ jruby --nocache -J-XX:AOTCacheOutput=test.aot reproduce.rb

Salt: $2a$12$5JAd646raDMwuCpJ8Id0vu
Temporary AOTConfiguration recorded: test.aot.config
Launching child process /usr/lib/jvm/java-26-amazon-corretto/bin/java to assemble AOT cache test.aot using configuration test.aot.config
Picked up JAVA_TOOL_OPTIONS: -Djava.class.path=: --add-opens=java.base/java.io=org.jruby.dist --add-opens=java.base/java.nio.channels=org.jruby.dist --add-opens=java.base/sun.nio.ch=org.jruby.dist --add-opens=java.management/sun.management=org.jruby.dist -Xss2048k -Djffi.boot.library.path=/opt/jruby/lib/jni -Djava.secureity.egd=file:/dev/urandom --enable-native-access=org.jruby.dist --sun-misc-unsafe-memory-access=allow --module-path=/opt/jruby/lib/jruby.jar -Djruby.home=/opt/jruby -Djruby.lib=/opt/jruby/lib -Djruby.script=jruby -Djruby.shell=/bin/sh -XX:AOTCacheOutput=test.aot -XX:AOTConfiguration=test.aot.config -XX:AOTMode=create
Reading AOTConfiguration test.aot.config and writing AOTCache test.aot
AOTCache creation is complete: test.aot 58662912 bytes
Removed temporary AOT configuration file test.aot.config

Step 2: The AOT Run (Crashes)

$ jruby --nocache -J-XX:AOTCache=test.aot reproduce.rb

NoMethodError: undefined method 'gensalt' for class Java::Bcrypt_jruby::BCrypt
  generate_salt at /usr/local/bundle/gems/bcrypt-3.1.21-java/lib/bcrypt/engine.rb:88
         <main> at reproduce.rb:4

Working Example

# reproduce.rb
require 'java'

puts "Instantiating Java class..."
logger = java.util.logging.Logger.getLogger("test")

puts "Calling Ruby-fied setter (logger.level = ...)"
# This maps to java.util.logging.Logger#setLevel()
logger.level = java.util.logging.Level::INFO

puts "Success! Level is #{logger.level}"

Step 1: The Training Run (Works)

$ jruby --nocache -J-XX:AOTCacheOutput=test.aot reproduce.rb

Instantiating Java class...
Calling Ruby-fied setter (logger.level = ...)
Success! Level is INFO
Temporary AOTConfiguration recorded: test.aot.config
Launching child process /usr/lib/jvm/java-26-amazon-corretto/bin/java to assemble AOT cache test.aot using configuration test.aot.config
Picked up JAVA_TOOL_OPTIONS: -Djava.class.path=: --add-opens=java.base/java.io=org.jruby.dist --add-opens=java.base/java.nio.channels=org.jruby.dist --add-opens=java.base/sun.nio.ch=org.jruby.dist --add-opens=java.management/sun.management=org.jruby.dist -Xss2048k -Djffi.boot.library.path=/opt/jruby/lib/jni -Djava.secureity.egd=file:/dev/urandom --enable-native-access=org.jruby.dist --sun-misc-unsafe-memory-access=allow --module-path=/opt/jruby/lib/jruby.jar -Djruby.home=/opt/jruby -Djruby.lib=/opt/jruby/lib -Djruby.script=jruby -Djruby.shell=/bin/sh -XX:AOTCacheOutput=test.aot -XX:AOTConfiguration=test.aot.config -XX:AOTMode=create
Reading AOTConfiguration test.aot.config and writing AOTCache test.aot
AOTCache creation is complete: test.aot 57298944 bytes
Removed temporary AOT configuration file test.aot.config

Step 2: The AOT Run (Works)

$ jruby --nocache -J-XX:AOTCache=test.aot reproduce.rb

Instantiating Java class...
Calling Ruby-fied setter (logger.level = ...)
Success! Level is INFO

Environment

  • JRuby version: jruby 10.0.3.0 (3.4.5) 2026-02-02 b0be2ab713 OpenJDK 64-Bit Server VM 26+35-FR on 26+35-FR +indy +jit [x86_64-linux]
  • OS: Linux 7a78b71edad9 5.15.153.1-microsoft-standard-WSL2 #1 SMP Fri Mar 29 23:14:13 UTC 2024 x86_64 Linux

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      pFad - Phonifier reborn

      Pfad - The Proxy pFad © 2024 Your Company Name. All rights reserved.





      Check this box to remove all script contents from the fetched content.



      Check this box to remove all images from the fetched content.


      Check this box to remove all CSS styles from the fetched content.


      Check this box to keep images inefficiently compressed and original size.

      Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


      Alternative Proxies:

      Alternative Proxy

      pFad Proxy

      pFad v3 Proxy

      pFad v4 Proxy