In my project class path poi 2.5 version is already there and on runtime i want to load poi 3.5 jar as for two java classes in my project require poi 3.5 version , so for that I have written class loader that will call the poi 3.5 jar on runtime please advise what is wrong now as it is not loading poi 3.5 version jar at runtime
below is my classloader
public class MyClassLoader {
private static final Class[] parameters = new Class[] {URL.class};
public static void addFile(String s) throws IOException
{
File f = new File(s);
addFile(f);
}
public static void addFile(File f) throws IOException
{
addURL(f.toURI().toURL());
}
public static void addURL(URL u) throws IOException
{
URLClassLoader sysloader = (URLClassLoader) ClassLoader.getSystemClassLoader();
Class sysclass = URLClassLoader.class;
try {
Method method = sysclass.getDeclaredMethod("addURL", parameters);
method.setAccessible(true);
method.invoke(sysloader, new Object[] {u});
} catch (Throwable t) {
t.printStackTrace();
throw new IOException("Error, could not add URL to system classloader");
}
}
}
and here i am calling from inside main method one of the method of poi 3.5 class which is newly added in 3.5 but it is not loaded
MyClassLoader.addFile("C:\\Release14branchupdated\\lib\\thirdparty\\POI-3.5\\poi-3.10-FINAL.jar");
Constructor<?> cs = ClassLoader.getSystemClassLoader().loadClass("org.apache.poi.ss.formula.FormulaCellCacheEntrySet").getConstructor(String.class);
System.out.println("$$$$$$$$$$"+cs.getName());
org.apache.poi.ss.formula.FormulaCellCacheEntrySet instance = (org.apache.poi.ss.formula.FormulaCellCacheEntrySet)cs.newInstance();
instance.iterator();
now upon execution the error that i am getting is not ble to find class FormulaCellCacheEntrySet
Related
With the following code snippet, I am trying to load some class files into my project to create an object. Unfortunately, it seems that something is missing, because there are no classes loaded. What is it?
private static void myClassloader() throws Exception
{
File file = new File(pathGeneratedClasses);
try
{
#SuppressWarnings("deprecation")
URL url = file.toURL();
URL[] urls = new URL[]{url};
ClassLoader sqlQuery = new URLClassLoader(urls);
Class myClass = sqlQuery.loadClass("de.cimt.jaxb.JaxCodeGen");
}
catch (Exception e)
{
System.out.println(e.toString());
}
}
sqlQuery.loadClass() will be returning the class you requested for, try assigning the returned value to something.
If no class is found then ClassNotFoundException will be thrown.
I am developing a wicket application which is running on jetty. My application should be able to load plugins from jar-files.
Thus I created a URLClassLoader which should load the plugin classes.
As a standard Java-application everything works, but when I want to load plugins on the server I get following errors: http://pastebin.com/e2JRAYTr
The Module interface that can not be found is defined in another project, but if I output the class-name in Wickets init() method like this
System.out.println(Module.class.getName())`
I get no error. So I think the other project is loaded correctly by Maven but there are issues with my custom jar-classloader.
The classloaders constructor where the action happens looks like this:
public WorkableLoader(final File jarFile) throws IOException, ClassNotFoundException, InstantiationException,
IllegalAccessException {
final URL[] urls = new URL[] { jarFile.toURI().toURL() };
classLoader = new URLClassLoader(urls);
final Class<?> cls = loadWorkableClass(jarFile);
workable = (Workable) cls.newInstance();
}
private Class<?> loadWorkableClass(final File jar) throws ClassNotFoundException, IOException {
try (final JarFile jarFile = new JarFile(jar)) {
final Enumeration<JarEntry> jarEntries = jarFile.entries();
while (jarEntries.hasMoreElements()) {
final JarEntry jarEntry = jarEntries.nextElement();
if (isClassFile(jarEntry.getName())) {
final String className = jarEntry.getName().replace("/", ".").replace(".class", "");
final Class<?> cls = classLoader.loadClass(className);
for (final Class<?> iface : cls.getInterfaces()) {
if (iface.equals(Module.class) || iface.equals(Bundle.class)) {
return cls;
}
}
}
}
} catch (final IOException e) {
throw e;
}
throw new ClassNotFoundException("Es konnte keine Workable-Klasse gefunden werden.");
}
The method isClass() just checks if the file ends with .class.
The last error of my code is at com.siemens.importer.workables.WorkableLoader.loadWorkableClass(WorkableLoader.java:137). Line 137 is the line
final Class<?> cls = classLoader.loadClass(className); of the loadWorkableClass() method. So how can I load classes with a custom classloader on a
jetty server?
Sorry for the huge output and thanks in advance!
This question already has answers here:
Java, Classpath, Classloading => Multiple Versions of the same jar/project
(5 answers)
Closed 8 years ago.
I have three Jar files.All jar files contain Same class TestServicesImpl And Same Method displayWeLcomeMessage() But having different messages(output) of displayWeLcomeMessage().
Example :
public void displayWeLcomeMessage() {
System.out.println("wecome msg of JAR version first");
}
public void displayWeLcomeMessage() {
System.out.println("wecome msg of JAR version two");
}
public void displayWeLcomeMessage() {
System.out.println("wecome msg of JAR version third");
}
I have One main application and it contains jars included. My main application calls displayWeLcomeMessage() method.
first JAR is added in classpath and second JAR is loaded with custom classloader and invoke method displayWeLcomeMessage().
File file = new File("C:/Users/amitk/Desktop/Test_1.0.2.jar");
#SuppressWarnings("deprecation")
URL url = file.toURL();
URL[] urls = new URL[]{url};
URLClassLoader loader = new URLClassLoader(urls);
Class classS = loader.loadClass("com.amit.servicesImpl.TestServicesImpl");
Object object = classS.newInstance();
Method getmsg = classS.getMethod("displayWeLcomeMessage");
getmsg.invoke(object);
but it displays the same message as in method of JAR first.
In my third JAR, i have changed the package name.
that is
com.amit.servicesImpl.TestServicesImpl is changed to com.amit.servicesImpl2.TestServicesImpl
and this time it works properly that is message of method of JAR 3 is displayed here.
so let me know the main issue behind this.and solution for this.
Maybe you have your JAR in your initial class loader.
URLClassLoader will check existing class in parent class loader before checking in its own space.
1) You can extend and modify this behavior:
package com.mytool;
import java.net.URL;
import java.net.URLClassLoader;
import java.net.URLStreamHandlerFactory;
import java.util.HashMap;
import java.util.Map;
public class MyURLClassLoader extends URLClassLoader {
private final Map<String, Class<?>> ourClasses = new HashMap<>();
public MyURLClassLoader(URL[] urls, ClassLoader parent) {
super(urls, parent);
}
public MyURLClassLoader(URL[] urls) {
super(urls);
}
public MyURLClassLoader(URL[] urls, ClassLoader parent, URLStreamHandlerFactory factory) {
super(urls, parent, factory);
}
#Override
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
synchronized (getClassLoadingLock(name)) {
// First, check if the class has already been loaded
Class<?> c = ourClasses.get(name);
if (c == null) {
// search in our paths
try {
c = findClass(name);
ourClasses.put(name, c);
} catch (ClassNotFoundException e) {
// ignore
}
}
if (c == null) {
c = findLoadedClass(name);
}
if (c != null) {
if (resolve) {
resolveClass(c);
}
return c;
}
// default search
return super.loadClass(name, resolve);
}
}
}
2) Or you can try to move our JAR and not load it at JVM start.
Note:
Instead of using a full reflexivity, I'll use an interface
loaded only by the initial classloader. Your object could implements it, and you'll be able to cast to this interface. If you do this with MyURLClassLoader, please don't add this interface in our dynamic loaded JAR!
Classloader will pick that class which was found first. If you are having 10 packages having same class then only that class will be picked which was introduced first.
It's a project downloaded from Web and I just changed the path to find the class which I want to make it load dynamically.Here are the codes in which I try to load the class on runtime.But I got a ClassNotFoundException eventually:
private static IExample newInstanceWithThrows() throws InstantiationException, IllegalAccessException, ClassNotFoundException {
URLClassLoader tmp =
new URLClassLoader(new URL[] {getClassPath()}) {
public Class<?> loadClass(String name)
throws ClassNotFoundException {
if ("example.Example".equals(name)
|| "example.Leak".equals(name))
return findClass(name);
return super.loadClass(name);
}
};
return (IExample) tmp.loadClass("example.Example")
.newInstance();
}
private static URL getClassPath() {
String dir = "/Users/longtuan/develop/rjc2011/classes/";
try {
//return new URL(dir);
File path = new File(dir);
return path.toURL();
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
}
And the path to class example.Example is:
/Users/longtuan/develop/java/rjc2011/classes/example
And the run command I used is:
java -classpath ./bin example.Main
Current directory is:
/Users/longtuan/develop/java/rjc2011
All the things of current directory are like this:
Example is the directory in which I put all the java files.I place the compiled class file in directory bin except the class example.Example which is put in classes lonely.
Above are all the informations I can give, thanks for any help.
I am trying to add jar file to classpath at runtime. I use this code
public static void addURL(URL u) throws IOException {
URLClassLoader sysloader = (URLClassLoader) ClassLoader
.getSystemClassLoader();
Class<URLClassLoader> sysclass = URLClassLoader.class;
try {
Method method = sysclass.getDeclaredMethod("addURL", parameters);
method.setAccessible(true);
method.invoke(sysloader, new Object[] { u });
System.out.println(u);
} catch (Throwable t) {
t.printStackTrace();
throw new IOException("Error");
}
}
System out prints this url:
file:/B:/Java/Tools/mysql-connector-java-5.1.18/mysql-connector-java-5.1.18/mysql-connector-java-5.1.18-bin.jar
I was check this path carefully, this jar exist. Even this test show that com.mysql.jdbc.
Driver class exists.
javap -classpath "B:\Java\Tools\mysql-connector-java-5.1.18\
mysql-connector-java-5.1.18\mysql-connector-java-5.1.18-bin.jar" com.mysql.jdbc.
Driver
Compiled from "Driver.java"
public class com.mysql.jdbc.Driver extends com.mysql.jdbc.NonRegisteringDriver i
mplements java.sql.Driver{
public com.mysql.jdbc.Driver() throws java.sql.SQLException;
static {};
}
But I still get java.lang.ClassNotFoundException when I use this Class.forName(driver).
What is wrong with this code?
The URL is ok, nevertheless you try to load a jar from classpath, so it means that yo need to have the file in cp first.
In your case you want to load a jar that is not in classpath so you have to use
URLClassLoader and for JAR you can use also the JARClassLoader
If you want some sample lesson on it:
http://docs.oracle.com/javase/tutorial/deployment/jar/jarclassloader.html
Here a sample I ran by myself see if helps you. It search the Logger class of Log4j that is not in my classpath, of course i got exception on invocation of the constructor since i did not pass the right params to the constructor
package org.stackoverflow;
import java.io.File;
import java.net.URL;
import java.net.URLClassLoader;
public class URLClassLoaderSample
{
public static void main(String[] args) throws Exception
{
File f = new File("C:\\_programs\\apache\\log4j\\v1.1.16\\log4j-1.2.16.jar");
URLClassLoader urlCl = new URLClassLoader(new URL[] { f.toURL()},System.class.getClassLoader());
Class log4jClass = urlCl.loadClass("org.apache.log4j.Logger");
log4jClass.newInstance();
}
}
Exception in thread "main" java.lang.InstantiationException: org.apache.log4j.Logger
at java.lang.Class.newInstance0(Class.java:357)
at java.lang.Class.newInstance(Class.java:325)
at org.stackoverflow.URLClassLoaderSample.main(URLClassLoaderSample.java:19)
Exception due to the wrong invocation, nevertheless at this stage we already found the class
Ok try the alternative approach with DataSource and not directly the Driver
Below is the code (working with oracle driver, i don't have my sql db, but the properties are the same)
Generally using the DataSource interface is the preferred approach since JDBC 2.0
The DataSource jar was not in the classpath neither for the test below
public static void urlCLSample2() throws Exception
{
File f = new File("C:\\_programs\\jdbc_drivers\\oracle\\v11.2\\ojdbc6.jar");
URLClassLoader urlCl = new URLClassLoader(new URL[] { f.toURL() }, System.class.getClassLoader());
// replace the data source class with MySQL data source class.
Class dsClass = urlCl.loadClass("oracle.jdbc.pool.OracleDataSource");
DataSource ds = (DataSource) dsClass.newInstance();
invokeProperty(dsClass, ds, "setServerName", String.class, "<put your server here>");
invokeProperty(dsClass, ds, "setDatabaseName", String.class, "<put your db instance here>");
invokeProperty(dsClass, ds, "setPortNumber", int.class, <put your port here>);
invokeProperty(dsClass, ds, "setDriverType",String.class, "thin");
ds.getConnection("<put your username here>", "<put your username password here>");
System.out.println("Got Connection");
}
// Helper method to invoke properties
private static void invokeProperty(Class dsClass, DataSource ds, String propertyName, Class paramClass,
Object paramValue) throws Exception
{
try
{
Method method = dsClass.getDeclaredMethod(propertyName, paramClass);
method.setAccessible(true);
method.invoke(ds, paramValue);
}
catch (Exception e)
{
throw new Exception("Failed to invoke method");
}
}