Author Topic: [Java] Loading JAR files in to the classpath at runtime  (Read 3902 times)

0 Members and 1 Guest are viewing this topic.

Offline Camel

  • Hero Member
  • *****
  • Posts: 1703
    • View Profile
    • BNU Bot
[Java] Loading JAR files in to the classpath at runtime
« on: September 08, 2007, 01:35:54 pm »
JavaOp appears to load plugin JARs in to the CP; if that's how it works, how's it done?

I want to be able to load JDBC drivers on-the-fly.

<Camel> i said what what
<Blaze> in the butt
<Camel> you want to do it in my butt?
<Blaze> in my butt
<Camel> let's do it in the butt
<Blaze> Okay!

Offline iago

  • Leader
  • Administrator
  • Hero Member
  • *****
  • Posts: 17914
  • Fnord.
    • View Profile
    • SkullSecurity
Re: [Java] Loading JAR files in to the classpath at runtime
« Reply #1 on: September 08, 2007, 02:38:26 pm »
It's opensource, have a look!

I seem to remember using Class.forName(), though. The Class class (ha!) has what you need, I think.

Offline Camel

  • Hero Member
  • *****
  • Posts: 1703
    • View Profile
    • BNU Bot
Re: [Java] Loading JAR files in to the classpath at runtime
« Reply #2 on: September 08, 2007, 03:45:39 pm »
Class.forName(..) just returns a <Class>; its purpose is to verify that a class is in the classpath, and to kick off any static initializers. That particular method will not add new JARs to the classpath.

I'll have a look at the rest of Class's methods, though.

[edit] Nevermind, you were right, iago. There are two forNames(); I didn't realize there was one that took a ClassLoader.

http://www.kfu.com/~nsayer/Java/dyn-jdbc.html
Code: [Select]
URL u = new URL("jar:file:/path/to/pgjdbc2.jar!/");
String classname = "org.postgresql.Driver";
URLClassLoader ucl = new URLClassLoader(new URL[] { u });
Driver d = (Driver)Class.forName(classname, true, ucl).newInstance();
DriverManager.registerDriver(new DriverShim(d));
DriverManager.getConnection("jdbc:postgresql://host/db", "user", "pw");
« Last Edit: September 08, 2007, 03:50:41 pm by Camel »

<Camel> i said what what
<Blaze> in the butt
<Camel> you want to do it in my butt?
<Blaze> in my butt
<Camel> let's do it in the butt
<Blaze> Okay!

Offline Camel

  • Hero Member
  • *****
  • Posts: 1703
    • View Profile
    • BNU Bot
Re: [Java] Loading JAR files in to the classpath at runtime
« Reply #3 on: September 09, 2007, 01:45:07 am »
Got it working. I wrote a class that provides a new forName(String), and will load any class out of any jar in the lib folder.

http://bnubot.googlecode.com/svn/trunk/BNUBot/src/net/bnubot/JARLoader.java

<Camel> i said what what
<Blaze> in the butt
<Camel> you want to do it in my butt?
<Blaze> in my butt
<Camel> let's do it in the butt
<Blaze> Okay!

Offline Joe

  • B&
  • x86
  • Hero Member
  • *****
  • Posts: 10319
  • In Soviet Russia, text read you!
    • View Profile
    • Github
Re: [Java] Loading JAR files in to the classpath at runtime
« Reply #4 on: September 10, 2007, 02:45:25 am »
I'm a bit rusty. The return from that method should be cast to match an Interface, correct?
I'd personally do as Joe suggests

You might be right about that, Joe.


Offline Camel

  • Hero Member
  • *****
  • Posts: 1703
    • View Profile
    • BNU Bot
Re: [Java] Loading JAR files in to the classpath at runtime
« Reply #5 on: September 10, 2007, 11:01:25 am »
I assume you're referring to JARLoader.forName(String)? Since it's a simple redirect to URLClassLoader.loadClass(String), you could consult the documentation for that method, but I'll take a stab at it anyways, even though I'm not sure I understand your question entirely.

The return value of the method is Class<?>, which is the standard way of specifying unknown origin in Java 1.5+ -- it's functionally equivalent to saying Class<Object>, but is more specific. With a Class object, you can induce reflection upon the class, create an instance according to the constructor "new ?()", and do a number of other things.

Why would you want to cast a Class<?> to an interface? It does implement a few things (Serializable, and three reflection-specific things), but the reduction is fruitless.

<Camel> i said what what
<Blaze> in the butt
<Camel> you want to do it in my butt?
<Blaze> in my butt
<Camel> let's do it in the butt
<Blaze> Okay!

Offline Joe

  • B&
  • x86
  • Hero Member
  • *****
  • Posts: 10319
  • In Soviet Russia, text read you!
    • View Profile
    • Github
Re: [Java] Loading JAR files in to the classpath at runtime
« Reply #6 on: September 10, 2007, 12:50:13 pm »
Can you access methods in the Class<?> just by calling them? The reason I thought you'd have to have to cast it to an interface is because the Loader doesn't know the loaded class' methods at compile-time.
I'd personally do as Joe suggests

You might be right about that, Joe.


Offline Chavo

  • x86
  • Hero Member
  • *****
  • Posts: 2219
  • no u
    • View Profile
    • Chavoland
Re: [Java] Loading JAR files in to the classpath at runtime
« Reply #7 on: September 10, 2007, 12:58:00 pm »
If you use reflection, you can invoke a method (or constructor) without knowing the class structure at compile time (although it helps to avoid invocation exceptions).  The javadoc on reflection is pretty good, you should read it.  I think I have an old topic in here somewhere about the performance differences associated with reflection as well (Myndfyre even made some pretty graphs ;))

Offline Camel

  • Hero Member
  • *****
  • Posts: 1703
    • View Profile
    • BNU Bot
Re: [Java] Loading JAR files in to the classpath at runtime
« Reply #8 on: September 10, 2007, 01:13:10 pm »
Can you access methods in the Class<?> just by calling them? The reason I thought you'd have to have to cast it to an interface is because the Loader doesn't know the loaded class' methods at compile-time.

The method returns an object of type Class<?>.

Class is defined like so:
Code: [Select]
public class Class<T> {
public T newInstance() throws ...;
}

Actually, if you look at the real definition, that's not how it works (it always returns an Object), but it's guaranteed to either return one of whatever the class was, or throw an exception. Therefore, it's safe to cast to what you were expecting without type-checking. Just be aware you could get a cast exception if you create something that you weren't expecting.

Code: [Select]
Driver d = (Driver)JARLoader.forName(driver).newInstance();
DriverManager.registerDriver(new DriverShim(d));

<Camel> i said what what
<Blaze> in the butt
<Camel> you want to do it in my butt?
<Blaze> in my butt
<Camel> let's do it in the butt
<Blaze> Okay!