5

Sorry, maybe this question is too silly or already answered, but I couldn't find it out.

I'm wondering if there is some known Java class-loader that is able to accept remote files in the classpath, i.e., entries like CLASSPATH="http://somewhere.net/library.jar:...".

Note that I am not talking about applets or Java Web Start. Think of an application that can use different back-ends (e.g., MySQL, Oracle), I'd like to prepare the classpath in a shell script, based on the user's back-end preference and have the class-loader to download the needed jar (the jdbc driver in this example) from a distribution server. I'm not talking about Maven either (the user just gets the binary distribution, I don't want to force them to build what they need from the sources).

zakmck
  • 2,022
  • 27
  • 37

3 Answers3

2

The SystemClassLoader is a URLClassLoader. You could try, I leave it to you:

Method method = URLClassLoader.class.getDeclaredMethod("addURL", new Class[]{URL.class});
method.setAccessible(true);
method.invoke(ClassLoader.getSystemClassLoader(), new Object[]{new URL("http://somewhere.net/library.jar")});  
Class.forName("your.remote.ClassName");

Let me know :)

Luigi R. Viggiano
  • 8,103
  • 6
  • 46
  • 60
  • Interesting, thanks Luigi! That code chunk works, however, I'm surprised that I cannot simply do: $ export CLASSPATH=http\://somewhere.net/library.jar $ java your.remote.ClassName that doesn't work, it tells me it didn't find the class. Am I still missing something? – zakmck Jan 10 '13 at 10:44
  • The classpath works only with filesystem paths. It's the same pattern as the unix $PATH variable. Maybe you can try asking Oracle to implement this feature for Java 9. The problem with specifying remote urls on classpath is that you need to download the jars somewhere in a repository (like mvn does). Otherwise it would slow down your app a lot during the startup. I think the limitation you describe is for practical purposes; but since networks are becoming faster, this may not be an issue in future (still... also application sizes are growing, so it still may be). – Luigi R. Viggiano Jan 10 '13 at 11:26
  • I think it would be a nice feature to have (and apparently quite easy to add). The start-up overhead problem could be solved via some caching mechanism. That's what I'm thinking of doing myself, but if Oracle or some other big player did it, it would be different (i.e., standardised). Thanks anyway! – zakmck Jan 10 '13 at 11:39
  • 1
    The optimal would be that you won't need to instantiate classes via reflection (Class.forName()) but just use them normally. I think it wouldn't be easy to design such feature. BTW some utility framework would be cool to implement (something like a *runtime* dependency system that works like maven): I imagine something like `MyObjectInterface myObject = loadFrom(url)` that can resolve also the dependencies as maven does; this is already possible, and not hard to implement. – Luigi R. Viggiano Jan 10 '13 at 11:47
1

You could use an URLClassLoader, but it would download the file every time, and would make the code more complex.

If you're using a shell script already, why don't you simply use curl to download the jar and place it in the classpath?

JB Nizet
  • 633,450
  • 80
  • 1,108
  • 1,174
  • The [documentation](http://docs.oracle.com/javase/7/docs/api/java/net/URLClassLoader.html) doesn't say it loads from http:// urls? – Miserable Variable Jan 09 '13 at 22:43
  • It loads from a URL. Itcould be anything, provided the JVM has an implementation of the protocol. And the JVM knows HTTP. – JB Nizet Jan 09 '13 at 22:44
  • So it does :) It would have been nice if the documentation said it uses `URLConnection`. – Miserable Variable Jan 09 '13 at 22:49
  • 1
    OTOH, what could it use other than a URLConnection to connect to a URL? If the URLClassLoader was limited to files, I guess they would have named it FileClassLoader and make it take File arguments instead of URLs :-) – JB Nizet Jan 09 '13 at 22:52
  • it's a bit more complicated, but yes, this is my plan B, thanks. – zakmck Jan 10 '13 at 10:49
1

Class loading is a complex process. It's possible that the regular classpath ClassLoader is a URLClassLoader in all runtime environments on all platforms, but I assume it wouldn't necessarily have to be.

One method for adding classpath entries is to add a Class-Path: property to a jarfile's META-INF/MANIFEST.MF file, and the space-separated values of that property are resolved with a URLClassLoader. (Maven adds some of its classpath entries to jarfile manifests as file:// URIs, implying that http:// or https:// would work too.) So even if you can't get URL-based classpath entries working in the normal Java classpath in some runtime environment, you should be able to get them working by specifying the URL in a manifest file.

(I'm not familiar with how Java WebStart works, but maybe that also makes use of URL-based classpath entries?)

Luke Hutchison
  • 6,034
  • 2
  • 30
  • 26