Reputation: 1445
I need to load a class file present on a different server and execute a method in the class file. I dont want to use http or RMI but want to apply this method. I am looking at URLClassLoader but am not getting anywhere. Can someone please give me an example of loading a class from a different server.
Upvotes: 1
Views: 140
Reputation: 11612
You can store your .class files in a dataase as BLOB objects. You should use a cache, track all the classes that you use in a simple HashMap so that you can only retrieve each class for once from the database.
The code point that you retrieve the class binaries from the database must be executed when the delegated parent class loader throws a ClassNotFoundException
.
@Override
public Class<?> findClass(String name) throws ClassNotFoundException {
Class cls = null;
try {
cls = parent.loadClass(name); // Delegate to the parent Class Loader
} catch (ClassNotFoundException clnfE) { // If parent fails, try to locate and load the class
byte[] bytes = new byte[0];
try {
bytes = loadClassFromDatabase(name);
} catch (SQLException sqlE) {
throw new ClassNotFoundException("Unable to load class", sqlE);
}
return defineClass(name, bytes, 0, bytes.length);
}
return cls;
}
And you can modify the method, which retrieves the class binaries. For example, you can retrieve class binaries from a database, an ftp server, or a simple file, or even a simple socket connection. Here is an example which that the class binaries retrieved from the database;
private byte[] loadClassFromDatabase(String name) throws SQLException {
PreparedStatement pstmt = null;
Connection connection = null;
try {
connection = DriverManager.getConnection(connectionString);
String sql = "SELECT CLASS FROM CLASSES WHERE CLASS_NAME = ?";
pstmt = connection.prepareStatement(sql);
pstmt.setString(1, name);
ResultSet rs = pstmt.executeQuery();
if (rs.next()) {
Blob blob = rs.getBlob(1);
byte[] data = blob.getBytes(1, (int) blob.length());
return data;
}
} catch (SQLException e) {
System.out.println("Unexpected exception: " + e.toString());
} catch (Exception e) {
System.out.println("Unexpected exception: " + e.toString());
} finally {
if (pstmt != null) {
pstmt.close();
}
if(connection != null) {
connection.close();
}
}
return null;
}
The method which retrieves the class binaries should return a byte array, then the class loader defines the class with defineClass(name, bytes, 0, bytes.length)
method. As it is obvious, the byte array can be retrieved from a database, a socket connection, a file reader,...
I've already written a simple demo running on the apache derby as an in-memory cache. You can check it out;
And the whole demo project;
https://github.com/bzdgn/simple-class-loader
Upvotes: 1