public static ScriptingContainerDelegateImpl create(
            final ClassLoader classLoader,
            final LocalContextScope delegateLocalContextScope,
            final LocalVariableBehavior delegateLocalVariableBehavior) {
        final Object scriptingContainer = createScriptingContainer(
                classLoader, delegateLocalContextScope, delegateLocalVariableBehavior);

        if (scriptingContainer == null) {
            return new ScriptingContainerDelegateImpl();
        }

        final Method method_callMethod_ALObject;
        final Method method_callMethod_LObject_LClass;
        final Method method_callMethod_LClass;
        final Method method_getProvider;
        final Method method_get_LString;
        final Method method_put_LString_LObject;
        final Method method_remove_LString;
        final Method method_runScriptlet_LString;
        try {
            method_callMethod_ALObject = scriptingContainer.getClass().getMethod(
                "callMethod", Object.class, String.class, Object[].class);
            method_callMethod_LObject_LClass = scriptingContainer.getClass().getMethod(
                "callMethod", Object.class, String.class, Object.class, Class.class);
            method_callMethod_LClass = scriptingContainer.getClass().getMethod(
                "callMethod", Object.class, String.class, Class.class);
            method_getProvider = scriptingContainer.getClass().getMethod(
                "getProvider");
            method_get_LString = scriptingContainer.getClass().getMethod(
                "get", String.class);
            method_put_LString_LObject = scriptingContainer.getClass().getMethod(
                "put", String.class, Object.class);
            method_remove_LString = scriptingContainer.getClass().getMethod(
                "remove", String.class);
            method_runScriptlet_LString = scriptingContainer.getClass().getMethod(
                "runScriptlet", String.class);
        } catch (NoSuchMethodException ex) {
            // Required methods are not implemented in ScriptingContainer of the JRuby version.
            return new ScriptingContainerDelegateImpl();  // TODO: Log.
        }

        final Class<?> class_RubyObject;
        try {
            class_RubyObject = classLoader.loadClass("org.jruby.RubyObject");
        } catch (ClassNotFoundException ex) {
            // `org.jruby.RubyObject` is not implemented in the JRuby version -- unlikely.
            return new ScriptingContainerDelegateImpl();  // TODO: Log.
        }

        final Class<?> class_Constants;
        try {
            class_Constants = classLoader.loadClass("org.jruby.runtime.Constants");
        } catch (ClassNotFoundException ex) {
            // `org.jruby.runtime.Constants` is not implemented in the JRuby version -- unlikely.
            return new ScriptingContainerDelegateImpl();  // TODO: Log.
        }
        final String jrubyVersion = (String) getStaticField_Constants(class_Constants, "VERSION");
        final String rubyVersion = (String) getStaticField_Constants(class_Constants, "RUBY_VERSION");

        final Method method_getRubyInstanceConfig;
        final Method method_getRuntime;
        try {
            final Class<?> class_LocalContextProvider =
                    classLoader.loadClass("org.jruby.embed.internal.LocalContextProvider");
            method_getRubyInstanceConfig = class_LocalContextProvider.getMethod("getRubyInstanceConfig");
            method_getRuntime = class_LocalContextProvider.getMethod("getRuntime");
        } catch (ClassNotFoundException | NoSuchMethodException ex) {
            // `org.jruby.embed.internal.LocalContextProvider` nor its required methods are not implemented.
            // It unlikely happens, but it is acceptable.
            return new ScriptingContainerDelegateImpl(
                jrubyVersion,
                rubyVersion,

                scriptingContainer,
                method_callMethod_ALObject,
                method_callMethod_LClass,
                method_callMethod_LObject_LClass,
                method_getProvider,
                method_get_LString,
                method_put_LString_LObject,
                method_remove_LString,
                method_runScriptlet_LString,

                class_RubyObject);
        }

        final Field field_COMPILE_INVOKEDYNAMIC = createField_Options(classLoader, "COMPILE_INVOKEDYNAMIC");
        final Method method_force_LString = createMethod_force_LString(classLoader);

        final Object const_CompileMode_OFF = createCompileMode(classLoader, "OFF");
        final Method method_setCompileMode_LCompileMode = createMethod_setCompileMode_LCompileMode(
                classLoader, const_CompileMode_OFF.getClass());

        return new ScriptingContainerDelegateImpl(
                jrubyVersion,
                rubyVersion,

                scriptingContainer,
                method_callMethod_ALObject,
                method_callMethod_LClass,
                method_callMethod_LObject_LClass,
                method_getProvider,
                method_get_LString,
                method_put_LString_LObject,
                method_remove_LString,
                method_runScriptlet_LString,

                class_RubyObject,

                method_getRubyInstanceConfig,

                field_COMPILE_INVOKEDYNAMIC,
                method_force_LString,

                const_CompileMode_OFF,
                method_setCompileMode_LCompileMode,

                method_getRuntime);
    }
Indirects onto JRuby not to require JRuby classes directly.

It calls methods of ScriptingContainer through reflection.

This trick enables Embulk:

<ul>
<li>To load a JRuby runtime (jruby-complete-*.jar) specified at runtime out of embulk-*.jar.
<li>To switch versions of JRuby without releasing or repackaging.
<li>To distribute Embulk without JRuby runtimes embedded.
</ul>
embulk-core/src/main/java/org/embulk/jruby/ScriptingContainerDelegateImpl.java