[ https://issues.apache.org/jira/browse/LOG4J2-1484?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Dawid Weiss updated LOG4J2-1484: -------------------------------- Description: The configuration permits "by-package" plugin lookup mechanism, for example: {code} <Configuration packages="foo.bar,foo.baz"> {code} I've encountered a problem where my application was picking up the plugins just fine before JAR postprocessing, but wouldn't find them afterwards, so I spent a few hours looking for the problem. Turns out the problem (in my case) was twofold. The first issue is inside log4j2's plugin lookup mechanism, the other was a consequence of the first one. 1. ResolverUtil.findInPackage uses undocumented side effects of ClassLoader.getResource Namely, this part: {code} public void findInPackage(final Test test, String packageName) { packageName = packageName.replace('.', '/'); final ClassLoader loader = getClassLoader(); Enumeration<URL> urls; try { urls = loader.getResources(packageName); } catch (final IOException ioe) { LOGGER.warn("Could not read package: " + packageName, ioe); return; } {code} ClassLoader's getResources method is only specified to work for actual resources, not for folders (or directories). That it works for packages now (at least in URLClassLoader) is merely a side-effect (and implementation detail) as class loaders are not obliged to enumerate packages (or resources within) and in fact they don't permit it from Java 9 on. I believe there is no sensible "fix" for this behavior; one could try to lookup {{META-INF/MANIFEST.MF}} to locate JAR files but this is also not guaranteed to exist, so it'd be hacking a hack... The best fix would be to require explicit names of the plugins/ resources that must be located and loaded, then the code would use the typical {{Class.forName(ClassLoader)}} idiom and delegate the actual lookup to Java. 2. The way to demonstrate that the above is a real problem is to create a perfectly legitimate JAR file that contains no ZIP dictionary entries for "directories" (inside the ZIP archive), only entries for the zipped classes. This is a valid JAR file, works with the JVM/ JDK just fine (because classes are looked up as exactly-named resources), but the above package-lookup mechanism won't work because the ZIP file contains no entries for "directories" to which packages are converted by the code. was: The configuration permits "by-package" plugin lookup mechanism, for example: {code} <Configuration packages="foo.bar,foo.baz"> {code} I've encountered a problem where my application was picking up the plugins just fine before JAR postprocessing, but wouldn't find them afterwards, so I spent a few hours looking for the problem. Turns out the problem (in my case) was twofold. The first issue is inside log4j2's plugin lookup mechanism, the other was a consequence of the first one. 1. ResolverUtil.findInPackage uses undocumented side effects of ClassLoader.getResource Namely, this part: {code} public void findInPackage(final Test test, String packageName) { packageName = packageName.replace('.', '/'); final ClassLoader loader = getClassLoader(); Enumeration<URL> urls; try { urls = loader.getResources(packageName); } catch (final IOException ioe) { LOGGER.warn("Could not read package: " + packageName, ioe); return; } {code} ClassLoader's getResources method is only specified to work for actual resources, not for folders (or directories). That it works for packages now (at least in URLClassLoader) is merely a side-effect (and implementation detail) as class loaders are not obliged to enumerate packages (or resources within) and in fact they don't permit it from Java 9 on. I believe there is no sensible "fix" for this behavior; one could try to lookup {{META-INF/MANIFEST.MF}} to locate JAR files but this is also not guaranteed to exist, so it'd be hacking a hack... The best fix would be to require explicit names of the plugins/ resources that must be located and loaded, then the code would use the typical {{Class.forName(ClassLoader)}} idiom and delegate the actual lookup to Java. 2. The way to demonstrate that the above is a real problem is to create a perfectly legitimate JAR file that contains no entries (inside the ZIP archive directory). This is a valid JAR file, works with the JVM/ JDK just fine (because classes are looked up as exactly-named resources), but the above package-lookup mechanism won't work because the ZIP file contains no entries for "directories" to which packages are converted by the code. > Plugin lookup via packages attribute is broken (because of the lookup method > used) > ---------------------------------------------------------------------------------- > > Key: LOG4J2-1484 > URL: https://issues.apache.org/jira/browse/LOG4J2-1484 > Project: Log4j 2 > Issue Type: Bug > Affects Versions: 2.6.2 > Reporter: Dawid Weiss > > The configuration permits "by-package" plugin lookup mechanism, for example: > {code} > <Configuration packages="foo.bar,foo.baz"> > {code} > I've encountered a problem where my application was picking up the plugins > just fine before JAR postprocessing, but wouldn't find them afterwards, so I > spent a few hours looking for the problem. > Turns out the problem (in my case) was twofold. The first issue is inside > log4j2's plugin lookup mechanism, the other was a consequence of the first > one. > 1. ResolverUtil.findInPackage uses undocumented side effects of > ClassLoader.getResource > Namely, this part: > {code} > public void findInPackage(final Test test, String packageName) { > packageName = packageName.replace('.', '/'); > final ClassLoader loader = getClassLoader(); > Enumeration<URL> urls; > try { > urls = loader.getResources(packageName); > } catch (final IOException ioe) { > LOGGER.warn("Could not read package: " + packageName, ioe); > return; > } > {code} > ClassLoader's getResources method is only specified to work for actual > resources, not for folders (or directories). That it works for packages now > (at least in URLClassLoader) is merely a side-effect (and implementation > detail) as class loaders are not obliged to enumerate packages (or resources > within) and in fact they don't permit it from Java 9 on. > I believe there is no sensible "fix" for this behavior; one could try to > lookup {{META-INF/MANIFEST.MF}} to locate JAR files but this is also not > guaranteed to exist, so it'd be hacking a hack... > The best fix would be to require explicit names of the plugins/ resources > that must be located and loaded, then the code would use the typical > {{Class.forName(ClassLoader)}} idiom and delegate the actual lookup to Java. > 2. The way to demonstrate that the above is a real problem is to create a > perfectly legitimate JAR file that contains no ZIP dictionary entries for > "directories" (inside the ZIP archive), only entries for the zipped classes. > This is a valid JAR file, works with the JVM/ JDK just fine (because classes > are looked up as exactly-named resources), but the above package-lookup > mechanism won't work because the ZIP file contains no entries for > "directories" to which packages are converted by the code. -- This message was sent by Atlassian JIRA (v6.3.4#6332) --------------------------------------------------------------------- To unsubscribe, e-mail: log4j-dev-unsubscr...@logging.apache.org For additional commands, e-mail: log4j-dev-h...@logging.apache.org