Use manifest from class’s jar when defining its package

Previously, when defining a package for a class, LaunchedURLClassLoader
would use the manifest from the first location that contained the
required package. If the package was split across multiple locations,
this could lead to the manifest from a jar other than the one that
contains the class being used.

This commit updates LaunchedURLClassLoader so that it will use the
manifest of the jar file that contains the class which triggered the
definition of the package.

Closes gh-5485
This commit is contained in:
Andy Wilkinson 2016-03-24 15:57:32 +00:00
parent 1d099035b1
commit c0b74119e0

View File

@ -105,7 +105,7 @@ public class LaunchedURLClassLoader extends URLClassLoader {
String packageName = className.substring(0, lastDot);
if (getPackage(packageName) == null) {
try {
definePackage(packageName);
definePackage(className, packageName);
}
catch (IllegalArgumentException ex) {
// Tolerate race condition due to being parallel capable
@ -122,17 +122,19 @@ public class LaunchedURLClassLoader extends URLClassLoader {
}
}
private void definePackage(final String packageName) {
private void definePackage(final String className, final String packageName) {
try {
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
@Override
public Object run() throws ClassNotFoundException {
String packageEntryName = packageName.replace(".", "/") + "/";
String classEntryName = className.replace(".", "/") + ".class";
for (URL url : getURLs()) {
try {
if (url.getContent() instanceof JarFile) {
JarFile jarFile = (JarFile) url.getContent();
if (jarFile.getEntry(packageEntryName) != null
if (jarFile.getEntry(classEntryName) != null
&& jarFile.getEntry(packageEntryName) != null
&& jarFile.getManifest() != null) {
definePackage(packageName, jarFile.getManifest(),
url);