NullPointerException was thrown when one of our customers tried to load latest DB2 JCC driver (db2jcc.jar - V10.1 and above) using a custom class loader ( like open source module NestedJarClassLoader). The same worked while loading old DB2 V8.2 db2jcc.jar driver (2.11.24).
Here is the error stack:
Caused by: java.lang.NullPointerException
at java.security.AccessController.doPrivileged(Native Method)
... 7 more
We reviewed the stack and found that the NullPointerException is thrown due to the com.ibm.pdq.cmx.client.DataSourceFactory class being not loaded, which is part of pdq.jar (which is for PureQuery feature Support). This pdq.jar is not part of the DB2 JCC driver download by default.
The pureQuery support was not in JCC 2.xx.xx (old drivers) but the latest drivers(JCC3.xx.xx) supports pureQuery. In order to support pureQuery,
newer JCC3.xx.xx loads the first class <com.ibm.pdq.cmx.client.DataSourceFactory> of pureQuery from pdq.jar file. In new drivers, JCC uses loadClass(String name) method of classloader to load the class.
If class was not found then the loadClass(String name) method will throw ClassNotFoundException. In new drivers, loadClass(String name) method is called on JCC ClassLoader to load the <com.ibm.pdq.cmx.client.DataSourceFactory> class from pdq.jar first.
If pdq.jar is in classpath, JCC driver loads <com.ibm.pdq.cmx.client.DataSourceFactory> class successfully and application gets the successful connection object.
If pdq.jar is not in classpath then JCC driver fails to find <com.ibm.pdq.cmx.client.DataSourceFactory> class, so the loadClass(String name) method fails to get the specified class and it will throw the ClassNotFoundException. Using ClassNotFoundException, JCC driver understands that pdq.jar is not in classpath and the driver then proceeds for other activity(e.g. loadDriver and connection etc.) by skipping purQuery features.
But in customer's environment, Using custom class loader, loadClass(String name) method behaved abnormal. If pdq.jar was not in classpath then loadclass(String name) method was returning <com.ibm.pdq.cmx.client.DataSourceFactory> object as NULL instead of throwing the ClassNotFoundException to JCC driver.
According to loadclass(String name) method specs, It is not required to handle the NullPointerException because if specified class is available then return the valid class object and if class is not found then throw the ClassNotFoundException. In absence of specified class, loadclass(String name) shouldn't return NULL, but the custom class loader was returning NULL and that caused the NullPointerException.
Customer did not see this issue with old driver, because, the old driver had not implemented the PureQuery feature, so the old driver doesn't call the API to load <com.ibm.pdq.cmx.client.DataSourceFactory> using custom class loader.
Once customer modified his custom class loader to handle this, he was able to successfully load the JCC driver.
Refer: loadClass(String name) method
Thanks for reading!