maven-issues mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Bence Sipka (Jira)" <j...@apache.org>
Subject [jira] [Commented] (MRESOLVER-94) NullPointerException if no Package is defined for the current class
Date Mon, 07 Oct 2019 08:04:00 GMT

    [ https://issues.apache.org/jira/browse/MRESOLVER-94?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16945661#comment-16945661
] 

Bence Sipka commented on MRESOLVER-94:
--------------------------------------

The code doesn't have packages in a way, that the ClassLoader that loads the maven-resolves
classes, doesn't call ClassLoader.definePackage for the loaded classes. This will result in
getClass().getPackage() to return null. Therefore, 
 this.getClass().getPackage().getImplementationVersion() will result in a NPE.

According to the documentation of Class.getPackage(), the method can return null, however
the implementations in DefaultSuperPomProvider and DefaultReportingConverter doesn't handle
this scenario.

I don't use the default packages.

An example for reproducing this:
{code:java}
public static void main(String[] args) throws Exception {
	Path jarpath = Paths.get("maven-resolver-fat-jar.jar");
	try (JarFile jar = new JarFile(jarpath.toFile())) {
		ClassLoader cl = new ClassLoader(null) {
			@Override
			protected Class<?> findClass(String name) throws ClassNotFoundException {
				ZipEntry entry = jar.getEntry(name.replace('.', '/') + ".class");
				if (entry != null) {
					try (InputStream is = jar.getInputStream(entry)) {
						ByteArrayOutputStream baos = new ByteArrayOutputStream();
						byte[] buf = new byte[4096];
						for (int read; (read = is.read(buf)) > 0;) {
							baos.write(buf, 0, read);
						}
						byte[] classbytes = baos.toByteArray();
						return defineClass(name, classbytes, 0, classbytes.length);
					} catch (IOException e) {
					}
				}
				return super.findClass(name);
			}
		};
		Class<?> defaultreportinconverterclass = cl.loadClass("org.apache.maven.model.plugin.DefaultReportingConverter");
		System.out.println("App.main() " + defaultreportinconverterclass);
		System.out.println("App.main() " + defaultreportinconverterclass.getPackage());
		defaultreportinconverterclass.getConstructor().newInstance();
	}
}
{code}
Minimal example for loading an affected class via a custom classloader from a fat JAR. The
maven-resolver-fat-jar.jar contains all classes required by the maven-resolver to operate.

The anonymous ClassLoader inner class loads the classes from the appropriate JAR entries.

The program will produce the following output:
{code:java}
App.main() class org.apache.maven.model.plugin.DefaultReportingConverter
App.main() null
Exception in thread "main" java.lang.reflect.InvocationTargetException
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
	at example.saker.maven.support.App.main(App.java:191)
Caused by: java.lang.NullPointerException
	at org.apache.maven.model.plugin.DefaultReportingConverter.<init>(DefaultReportingConverter.java:56)
	... 5 more
{code}
As you can see, a NullPointerException occurs when the DefaultReportingConverter class is
being instantiated, as it will call this.getClass().getPackage().getImplementationVersion().
But due to the fact, that no definePackage is called by the ClassLoader, it throws a NPE.

The same kind of error occurs when using DefaultSuperPomProvider.

> NullPointerException if no Package is defined for the current class
> -------------------------------------------------------------------
>
>                 Key: MRESOLVER-94
>                 URL: https://issues.apache.org/jira/browse/MRESOLVER-94
>             Project: Maven Resolver
>          Issue Type: Bug
>          Components: resolver
>    Affects Versions: 1.4.1
>         Environment: Windows 10, Java 8, custom classloading
>            Reporter: Bence Sipka
>            Priority: Minor
>
> When the maven-resolver and related classes are used with a {{ClassLoader}} that doesn't
define a java.lang.Package object for the loaded classes, the library throws a {{NullPointerException}}.
> Scenario: I'm using the maven-resolver classes to resolver artifacts from various repositories.
I package the app, and deploy it to a custom environment where the {{ClassLoader}} for the
app doesn't define a {{Package}} for the loaded classes. In these cases, when the maven-resolver
library calls {{this.getClass().getPackage().getImplementationVersion()}} then a {{NullPointerException}}
will occurr.
>  The following classes are affected:
>  {{DefaultSuperPomProvider.getSuperModel():81}}
>  {{DefaultReportingConverter.<init>:56}}
> Code around the locations:
> {code:java}
> String modelId = "org.apache.maven:maven-model-builder:"
>     + this.getClass().getPackage().getImplementationVersion() + ":super-pom";
> InputSource inputSource = new InputSource();
> inputSource.setModelId( modelId );
> {code}
> This exception makes the library unportable to different environments.
> Workaround:
> Implement a custom variant of the above classes that circumvent these parts of the code.
> Possible solution:
> Null checks, and hard coding the version number.



--
This message was sent by Atlassian Jira
(v8.3.4#803005)

Mime
View raw message