Reputation: 5441
I'm trying to do java class loading. I'm using eclipse (luna) with 1.8.0_25 on a macos yosemite.
I'm using the following code in order to do it. It's working, until it reaches a class that has a dependency that isn't contained inside the jar that I'm loading classes from. Neither on the environment.
I'm not interested in this classes, so, it's safe to ignore then. So, I put it inside a try/catch and just log it.
But, when the exception occurs, the execution is canceled.
The exception (summarized) is:
Exception in thread "main" java.lang.NoClassDefFoundError: org/aspectj/runtime/internal/AroundClosure
Caused by: java.lang.ClassNotFoundException: org.aspectj.runtime.internal.AroundClosure
It rises at the exact line that is inside the inner try/catch block.
Why? Shouldn't the try/catch just log it and move on?
URLClassLoader ucl = null;
try {
URL url = Utils.getURIFromPath(jarFilePath).toURL();
URL[] urls = new URL[] { url };
ucl = new URLClassLoader(urls);
for (String tmp : classes) {
String clazz = tmp.substring(0, tmp.indexOf(".class")).replaceAll("/", ".");
try {
ucl.loadClass(clazz);
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
}
}
} catch (MalformedURLException e) {
LOGGER.error(e.getMessage(), e);
} finally {
if (ucl != null) {
try {
ucl.close();
} catch (IOException e) {
LOGGER.error(e.getMessage(), e);
}
}
}
Upvotes: 3
Views: 6490
Reputation: 6104
Ok then try this:
catch (Throwable e) {
LOGGER.error(e.getMessage(), e);
}
Although using the above code will handle both Errors and Exceptions for you (both extend from Throwable
), but it's not the right way to do it, only in very special cases do we handle errors using try-catch, errors are something we need to check in our code and resolve them.
Upvotes: 3
Reputation: 95948
NoClassDefFoundError
is an Error, not an Exception
, you should never1 try to catch
an error, as stated here, catching it won't help you.
Check your classpath and fix it.
1 In some cases you might want to catch
an error and handle it accordingly, as stated in the comments, maybe "never" is a little bit strong
Upvotes: 7
Reputation: 17935
It seems that one of the classes that you're using, probably one of the classes that you're trying to load with loadClass
, has a dependency to classes from AspectJ, but the ClassLoader does not find the AspectJ classes. A possible solution is to make sure that AspectJ is on your classpath when you execute this.
It might also be that AspectJ already is on the classpath. If that's the case, it's just that your URLClassLoader
doesn't know of your ClassPath. You might want to construct the URLClassLoader
with a parent ClassLoader
in place, like this:
ucl = new URLClassLoader(urls, getClass().getClassLoader());
The reason why the program doesn't just move on is that you're catching Exception
. The hierarchy is class Throwable
, class Exception extends Throwable
and class Error extends Throwable
, so catch (Exception e)
will not catch Error
. You might want to use catch(Exception | NoClassDefFoundError e)
in this special case. Usually, catching Errors is not a good idea, but sometimes there are reasonable exceptions for errors like NoClassDefFoundError
, OutOfMemoryError
or StackOverflowError
.
Upvotes: 2