Java class with possible run-time flaws

I have a utility class U, which depends on the X library and should go in a package that will be used from programs with X available (where it should do its usual things) and places without X (where it should not do anything). Without dividing the class into two, I found a simple template that solves this:

package foo; import bar.MisteriousX; public class U { static private boolean isXPresent = false; static { try { isXPresent = (null != U.class.getClassLoader().loadClass("bar.MisteriousX")); } catch (Exception e) { // loading of a sample X class failed: no X for you } } public static void doSomething() { if (isXPresent) { new Runnable() { public void run() { System.err.println("X says " + MisteriousX.say()); } }.run(); } else { System.err.println("X is not there"); } } public static void main(String args[]) { doSomething(); } } 

With this pattern, U requires compiling X, but it works as expected when starting with or without X. If all calls to the X library are inside the inner classes, this code throws an exception to the loader class.

Questions: is import permission allowed to work this way everywhere, or will it depend on the JVM / ClassLoader implementation? Is it installed for this? Is the code snippet above too hacky to make it into production?

+4
source share
2 answers

As a rule, when a class is first loaded, then if it belongs to a class that does not exist, this can lead to an error. So yes, if one class makes a check, and the other class actually gets access to the external package without reflection, it will work as intended, at least in all the implementations that I have seen so far. It does not have to be an inner class.

the link section in the JVM specifications gives you more freedom to implement. If you do not use a two-class approach, then checking U in the implementation using a trusted link will result in an attempt to load X , which will result in a LinkageError . Specifications do not require verification of the reference class, but it does not prohibit such early verification. However, this requires that

any error detected during resolution must be thrown to a point in the program (directly or indirectly) uses a symbolic link to a class or interface.

It seems you should be safe to assume that the error only occurs when you actually access your inner class. If you look at the history of this answer, you will find that I have already changed my mind twice, so this time there will be no guarantee that I will read it correctly ...: - /

+3
source

I am doing a similar thing in jOOQ to load additional logging framework dependencies. I share your feelings about the fact that this is a little hack. An example of a field initialization code fragment, depending on the availability of the class:

 public final class JooqLogger { private org.slf4j.Logger slf4j; private org.apache.log4j.Logger log4j; private java.util.logging.Logger util; public static JooqLogger getLogger(Class<?> clazz) { JooqLogger result = new JooqLogger(); // Prioritise slf4j try { result.slf4j = org.slf4j.LoggerFactory.getLogger(clazz); } // If that not on the classpath, try log4j instead catch (Throwable e1) { try { result.log4j = org.apache.log4j.Logger.getLogger(clazz); } // If that not on the classpath either, ignore most of logging catch (Throwable e2) { result.util= java.util.logging.Logger.getLogger(clazz.getName()); } } return result; } [...] 

And then, later, the registrar switch, depending on previously loaded classes:

 public boolean isTraceEnabled() { if (slf4j != null) { return slf4j.isTraceEnabled(); } else if (log4j != null) { return log4j.isTraceEnabled(); } else { return util.isLoggable(Level.FINER); } } 

The rest of the source code can be seen here . In fact, I have a compile-time dependency with both slf4j and log4j, which I render optionally at runtime using a similar template like you.

This can cause problems in OSGi environments, for example, when loading classes is a bit more complicated than using standard JDK / JRE loading mechanisms. However, so far I have not been informed of any problems.

+3
source

All Articles