Reputation: 7784
I want to load a library in separated classloader because don't want to add directly as dependency to do not conflict with other versions in the project. I created a loader:
public LibLoader(String resourcePath) {
//resourcePath="/lib/Log4JHack-1.0.jar"
URL url = getClass().getResource(resourcePath);
loader = new URLClassLoader(new URL[] {url}, getClass().getClassLoader());
}
url = [file:/D:/..../lib/Log4JHack-1.0.jar]
if url is a file, then it works well.
url = [jar:file:/C:/..../Log4JHackLoader-1.0.jar!/lib/Log4JHack-1.0.jar]
if url is a jar:file (jar inside jar), then it don't work:
ERROR StatusLogger Unable to open jar:jar:file:/C:/Users/Dani/.m2/repository/hu/daniel/hari/log4jhack/Log4JHackLoader/1.0/Log4JHackLoader-1.0.jar!/lib/Log4JHack-1.0.jar!/META-INF/log4j-provider.properties java.net.MalformedURLException: no !/ in spec
at java.net.URL.<init>(URL.java:620)
at java.net.URL.<init>(URL.java:483)
at java.net.URL.<init>(URL.java:432)
at java.net.JarURLConnection.parseSpecs(JarURLConnection.java:175)
at java.net.JarURLConnection.<init>(JarURLConnection.java:158)
at sun.net.www.protocol.jar.JarURLConnection.<init>(JarURLConnection.java:81)
at sun.net.www.protocol.jar.Handler.openConnection(Handler.java:41)
at java.net.URL.openConnection(URL.java:972)
at java.net.URL.openStream(URL.java:1038)
at org.apache.logging.log4j.util.ProviderUtil.loadProvider(ProviderUtil.java:79)
at org.apache.logging.log4j.util.ProviderUtil.<init>(ProviderUtil.java:66)
at org.apache.logging.log4j.util.ProviderUtil.lazyInit(ProviderUtil.java:122)
at org.apache.logging.log4j.util.ProviderUtil.hasProviders(ProviderUtil.java:106)
at org.apache.logging.log4j.LogManager.<clinit>(LogManager.java:91)
at hu.daniel.hari.log4jpattern.logrenderer.log4j.log4j.capture.log4j2.StringLoggerCapture.<clinit>(StringLoggerCapture.java:34)
at hu.daniel.hari.log4jpattern.logrenderer.log4j.Log4j2Hack.doRender(Log4j2Hack.java:30)
at hu.daniel.hari.log4jpattern.logrenderer.log4j.Log4j2Hack.render(Log4j2Hack.java:23)
at hu.daniel.hari.log4jpattern.logrenderer.log4j.renderer.AbstractLog4jRendererAdapter.render(AbstractLog4jRendererAdapter.java:25)
at hu.daniel.hari.log4jpattern.logrenderer.service.LogRendererServiceImpl.getOutput(LogRendererServiceImpl.java:44)
at hu.daniel.hari.log4jpattern.logrenderer.service.LogRendererServiceImpl.render(LogRendererServiceImpl.java:37)
at hu.daniel.hari.log4jpattern.logrenderer.TestMain.main(TestMain.java:14)
Caused by: java.lang.NullPointerException: no !/ in spec
at sun.net.www.protocol.jar.Handler.parseAbsoluteSpec(Handler.java:171)
at sun.net.www.protocol.jar.Handler.parseURL(Handler.java:151)
at java.net.URL.<init>(URL.java:615)
... 20 more
Since I want to pack the loadable Log4JHack-1.0.jar to Log4JHackLoader-1.0.jar, I need a solution for loading from inside jar.
Upvotes: 0
Views: 1722
Reputation: 547
The github.com/squark-io/nested-jar-classloader project is able to load classes in nested jar files, but has a lot of external dependencies. I added this same mechanism in my project (sourceforge.net/projects/mdiutilities/) but in this case without external dependencies.
These two projects do not work by making a temporary copy of the nested jar files, but directly load the classes bytes.
Upvotes: 0
Reputation: 5443
It's not 100% clear to me what you're trying to do here. Why are you trying to include conflicting dependencies in your classpath?
In any case, this is a known limitation of UrlClassLoader
. Have you considered extracting the nested jar as a temporary file on the file system, and then pointing your class loader to it?
Upvotes: 1