Skip to content

[native-image] Any chance to support dynamic class loading if the JARs loaded by code is given at native-image compiling time? #461

@cqjjjzr

Description

@cqjjjzr

From the "LIMITATIONS.md" I know the dynamic class loading is not supported.
But is there any way to support it if the JARs loaded is already known when compiling and can the native-image tool statically link it into the built program?
Also, can the tool just analyze the invocations to Class.forName and find out the class being loaded if it's invoked by a const string class name.(Like forcely loading JDBC database drivers)
The reason for supporting this is for plugin supports. Many JVM programs supports dynamic plugin loading or modding. If static linking can be supported it would be greatly helpful.
Thanks.

Activity

changed the title [-][native-image] Any change to support dynamic class loading if the JARs loaded by code is given at native-image compiling time?[/-] [+][native-image] Any chance to support dynamic class loading if the JARs loaded by code is given at native-image compiling time?[/+] on Jun 11, 2018
cstancu

cstancu commented on Jun 11, 2018

@cstancu
Member

@cqjjjzr thank you for your comment. Yes, the features that you mentioned are not available yet, but we plan to implement them. They should be available soon.

self-assigned this
on Jun 13, 2018
cstancu

cstancu commented on Jun 30, 2018

@cstancu
Member

@cqjjjzr we added ClassLoader support. Please see #470 (comment) for details. (Please note that this does not include analyzing Class.forName() to automatically discover dynamically loaded classes, you still need to register the classes via the reflection configuration files.That feature is still under development as it is part of a bigger change set.)

cstancu

cstancu commented on Jul 26, 2018

@cstancu
Member

@cqjjjzr 3c85875 improves native-image reflection support by automatically detecting reflective calls and intrinsifying them to the corresponding target elements statically. This includes analysis of Class.forName() as discussed above. Please read the updated REFLECTION.md for details.

behrangsa

behrangsa commented on May 12, 2019

@behrangsa

@cstancu does that mean GraalVM would eventually support scenarios like this:

Let's say I have a program that has a pluggable architecture. It has a Plugin interface that can be implemented by third parties:

package org.behrang.program;

public interface Plugin {

    String process(String input);

}

The entry point of the program looks for a CLI argument named --plugin, the fully qualified name of the implementation that the user wants to use:

package org.behrang.program;

public class Main {

    public static void main(String[] args) throws Exception {
        String pluginClassname = null;
        for (int i = 0; i < args.length; i++) {
            if ("--plugin".equals(args[i]) && args.length > i + 1) {
                pluginClassname = args[i + 1];
                break;
            }
        }

        if (pluginClassname == null) {
            System.err.println("--plugin is required");
            System.exit(1);
        }

        Class<?> pluginClass = Class.forName(pluginClassname);
        Plugin p = (Plugin) pluginClass.getDeclaredConstructor().newInstance();

        System.out.println(p.process("Hello, World!"));
    }

}

It then creates an instance of the plugin and invokes it:

Class<?> pluginClass = Class.forName(pluginClassname);
Plugin p = (Plugin) pluginClass.getDeclaredConstructor().newInstance();

System.out.println(p.process("Hello, World!"));

A third-party can implement a plugin by implementing this interface:

package org.behrang.plugin;

import org.behrang.program.Plugin;

public class SamplePlugin implements Plugin {
    @Override
    public String process(String s) {
        return "org.behrang.plugin.SamplePlugin: " + s;
    }
}

Finally, the user can put the JAR file for the plugin in the classpath and run the program:

$ java --class-path /path/to/program.jar:/path/to/plugin.jar \
                  org.behrang.program.Main \
                  --plugin org.behrang.plugin.SamplePlugin

org.behrang.plugin.SamplePlugin: Hello, World!

In real-world applications the plugin architecutre might use a class path and/or MANIFEST.MF scanner or another approach to load the plugin class.

There are many programs that work like this. For example in a static site generator a user can choose what library to use for processing markdown.

Will GraalVM support use cases like this? E.g.: a native image program that can load a custom library at execution time/runtime?

Or in this example, creating a native image of program.jar that can use a user's chosen plugin implementation in JAR (or binary/so) format?

guizmaii

guizmaii commented on Aug 18, 2021

@guizmaii

Any answer to @behrangsa questions? We're many to like his comment. It seems there's a community interest in this possibility!

Umartahir93

Umartahir93 commented on Sep 12, 2021

@Umartahir93

I am also kind of interested in this feature. Right now, we are running jvm with in-built JIT which is kind of doing job for us on our machines. But due to some requirement, we need to provide our obfuscated jar to one of our clients who will run it on their machines.

I tried exploring different obfuscation types which would provide me ultimate security, one approach I came out was to provide "native exe" to client so that he can run it on their env and at the same time we save ourselves from reverse engineering techniques.

But right now, I think only graal provides facility to convert whole program to native-image. But here problem is that we cannot load a jar file dynamically. If something exists like that native-image can work with a dynamic jar that would resolve problem.

P/S client has some hashing logic in this jar which he wont provide so, I am kind of stuck here to come out with a little bit of better approach.

ccwxl

ccwxl commented on Dec 8, 2021

@ccwxl

I am also kind of interested in this feature. Right now, we are running jvm with in-built JIT which is kind of doing job for us on our machines. But due to some requirement, we need to provide our obfuscated jar to one of our clients who will run it on their machines.

I tried exploring different obfuscation types which would provide me ultimate security, one approach I came out was to provide "native exe" to client so that he can run it on their env and at the same time we save ourselves from reverse engineering techniques.

But right now, I think only graal provides facility to convert whole program to native-image. But here problem is that we cannot load a jar file dynamically. If something exists like that native-image can work with a dynamic jar that would resolve problem.

P/S client has some hashing logic in this jar which he wont provide so, I am kind of stuck here to come out with a little bit of better approach.

same scene

ivanooi

ivanooi commented on Feb 22, 2022

@ivanooi

that reminds me Excelsior Jet JVM which compile java into native code, at the same time they able to compile any downloaded jar into dll as well.

DevSrSouza

DevSrSouza commented on Apr 25, 2022

@DevSrSouza

Any updates on this?

ghost

ghost commented on Jul 19, 2022

@ghost

Same need than behrangsa. We plan to fully migrate Reqchecker to the great Graal native feature, a basic plugin mechanism would be great.

9 remaining items

Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

    Development

    No branches or pull requests

      Participants

      @behrangsa@guizmaii@cstancu@oeresundsgruppen@cqjjjzr

      Issue actions

        [native-image] Any chance to support dynamic class loading if the JARs loaded by code is given at native-image compiling time? · Issue #461 · oracle/graal