调用 属性 的 getter 方法时发生 NullPointerException

NullPointerException occurred while invoking getter method of a property

我正在尝试获取由 JavaEE 服务器管理的 DataSource 和 Connection 对象的属性(在这种情况下,我 运行ning WebSphere Application Server 和 Db2 作为 RDBMS)。

我写了下面的代码。

public class ClassInfo {
    protected static final String NOT_APPLICABLE = "N/A";
    protected static final String UNKNOWN = "unkown";

    public static LinkedHashMap<String, String[]> getLinkedHashMap(Object obj) {
        LinkedHashMap<String, String[]> map = new LinkedHashMap<String, String[]>();
        BeanInfo bi = null;
        PropertyDescriptor[] pd = null;
        String name, type, value, getter, setter;
        Method m;
        try {
            bi = Introspector.getBeanInfo(obj.getClass());
        } catch (IntrospectionException e) {
            e.printStackTrace();
        }
        pd = bi.getPropertyDescriptors();
        for (int i = 0; i < pd.length; i++) {
            name = pd[i].getName();
            type = pd[i].getPropertyType().getName();
            m = pd[i].getReadMethod();
            if (m != null) {
                getter = m.getName();
                try {
                    value= m.invoke(obj).toString();
                } catch (Exception e) {
                    System.err.println("Exception occured while procession " + m.getName() + " --- " + e.getMessage());
                    e.printStackTrace();
                    value = UNKNOWN + " (getter is " + e.getMessage() + " )";
                }
            } else {
                getter = NOT_APPLICABLE;
                value = UNKNOWN + " (getter method is not available)";
            }
            m = pd[i].getWriteMethod();
            if (m != null) {
                setter = m.getName();
            } else {
                setter = NOT_APPLICABLE;
            }
            map.put(name, new String[] { type, getter, setter, value });
        }
    return map;
}

这是我的 Servlet 代码。

Context ctx = new InitialContext();
DataSource ds = (DataSource) ctx.lookup("jdbc/db2access");
LinkedHasMap<String, String> map = ClassInfo. getLinkedHashMap(ds);
... and more

我 运行 这个 Servlet 并从我的代码中得到了有趣的输出。 有 属性 个名为 "XADataSource"、"active"、"connection"(以及更多)的字段及其名为 "isXADataSource()"、"isActive()" 的 getter 方法, "getConnection()" 分别.

"isXADataSource()" 返回非空对象,其值可以通过 "toString()".

检索

NullPointerException 在调用此 "isActive()" 时发生,尽管我已检查 Method 对象不为 null。这是实际捕获此异常的代码块。

m = pd[i].getReadMethod();
if(m != null) {
    getter = m.getName();              //not null
    value = m.invoke(obj).toString();  //throws NullPointerException
}

这是堆栈跟踪日志。

[2/4/18 8:33:59:281 JST] 000000aa SystemErr     R Exception occured while procession isActive --- null
[2/4/18 8:33:59:282 JST] 000000aa SystemErr     R java.lang.reflect.InvocationTargetException
[2/4/18 8:33:59:283 JST] 000000aa SystemErr     R   at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[2/4/18 8:33:59:283 JST] 000000aa SystemErr     R   at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:90)
[2/4/18 8:33:59:284 JST] 000000aa SystemErr     R   at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:55)
[2/4/18 8:33:59:284 JST] 000000aa SystemErr     R   at java.lang.reflect.Method.invoke(Method.java:508)
[2/4/18 8:33:59:284 JST] 000000aa SystemErr     R   at net.mognet.servlet.ClassInfo.getLinkedHashMap(ClassInfo.java:35)
[2/4/18 8:33:59:285 JST] 000000aa SystemErr     R   at net.mognet.servlet.ClassInfo.exposeAsMarkdown(ClassInfo.java:61)
[2/4/18 8:33:59:286 JST] 000000aa SystemErr     R   at net.mognet.servlet.JDBCProperty.doGet(JDBCProperty.java:58)
[2/4/18 8:33:59:286 JST] 000000aa SystemErr     R   at javax.servlet.http.HttpServlet.service(HttpServlet.java:687)
[2/4/18 8:33:59:287 JST] 000000aa SystemErr     R   at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
[2/4/18 8:33:59:287 JST] 000000aa SystemErr     R   at com.ibm.ws.webcontainer.servlet.ServletWrapper.service(ServletWrapper.java:1235)
[2/4/18 8:33:59:288 JST] 000000aa SystemErr     R   at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:779)
[2/4/18 8:33:59:288 JST] 000000aa SystemErr     R   at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:478)
[2/4/18 8:33:59:288 JST] 000000aa SystemErr     R   at com.ibm.ws.webcontainer.servlet.ServletWrapperImpl.handleRequest(ServletWrapperImpl.java:178)
[2/4/18 8:33:59:289 JST] 000000aa SystemErr     R   at com.ibm.ws.webcontainer.filter.WebAppFilterManager.invokeFilters(WebAppFilterManager.java:1124)
[2/4/18 8:33:59:289 JST] 000000aa SystemErr     R   at com.ibm.ws.webcontainer.servlet.CacheServletWrapper.handleRequest(CacheServletWrapper.java:82)
[2/4/18 8:33:59:289 JST] 000000aa SystemErr     R   at com.ibm.ws.webcontainer.WebContainer.handleRequest(WebContainer.java:963)
[2/4/18 8:33:59:290 JST] 000000aa SystemErr     R   at com.ibm.ws.webcontainer.WSWebContainer.handleRequest(WSWebContainer.java:1817)
[2/4/18 8:33:59:290 JST] 000000aa SystemErr     R   at com.ibm.ws.webcontainer.channel.WCChannelLink.ready(WCChannelLink.java:382)
[2/4/18 8:33:59:291 JST] 000000aa SystemErr     R   at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleDiscrimination(HttpInboundLink.java:465)
[2/4/18 8:33:59:291 JST] 000000aa SystemErr     R   at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleNewRequest(HttpInboundLink.java:532)
[2/4/18 8:33:59:291 JST] 000000aa SystemErr     R   at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.processRequest(HttpInboundLink.java:318)
[2/4/18 8:33:59:292 JST] 000000aa SystemErr     R   at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.ready(HttpInboundLink.java:289)
[2/4/18 8:33:59:292 JST] 000000aa SystemErr     R   at com.ibm.ws.ssl.channel.impl.SSLConnectionLink.determineNextChannel(SSLConnectionLink.java:1187)
[2/4/18 8:33:59:292 JST] 000000aa SystemErr     R   at com.ibm.ws.ssl.channel.impl.SSLConnectionLink$MyReadCompletedCallback.complete(SSLConnectionLink.java:694)
[2/4/18 8:33:59:293 JST] 000000aa SystemErr     R   at com.ibm.ws.ssl.channel.impl.SSLReadServiceContext$SSLReadCompletedCallback.complete(SSLReadServiceContext.java:1833)
[2/4/18 8:33:59:293 JST] 000000aa SystemErr     R   at com.ibm.ws.tcp.channel.impl.AioReadCompletionListener.futureCompleted(AioReadCompletionListener.java:175)
[2/4/18 8:33:59:294 JST] 000000aa SystemErr     R   at com.ibm.io.async.AbstractAsyncFuture.invokeCallback(AbstractAsyncFuture.java:217)
[2/4/18 8:33:59:294 JST] 000000aa SystemErr     R   at com.ibm.io.async.AsyncChannelFuture.fireCompletionActions(AsyncChannelFuture.java:161)
[2/4/18 8:33:59:294 JST] 000000aa SystemErr     R   at com.ibm.io.async.AsyncFuture.completed(AsyncFuture.java:138)
[2/4/18 8:33:59:295 JST] 000000aa SystemErr     R   at com.ibm.io.async.ResultHandler.complete(ResultHandler.java:204)
[2/4/18 8:33:59:295 JST] 000000aa SystemErr     R   at com.ibm.io.async.ResultHandler.runEventProcessingLoop(ResultHandler.java:775)
[2/4/18 8:33:59:296 JST] 000000aa SystemErr     R   at com.ibm.io.async.ResultHandler.run(ResultHandler.java:905)
[2/4/18 8:33:59:296 JST] 000000aa SystemErr     R   at com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.java:1909)
[2/4/18 8:33:59:296 JST] 000000aa SystemErr     R Caused by: java.lang.NullPointerException
[2/4/18 8:33:59:297 JST] 000000aa SystemErr     R   at com.ibm.ws.rsadapter.jdbc.WSJdbcDataSource.isActive(WSJdbcDataSource.java:1203)
[2/4/18 8:33:59:298 JST] 000000aa SystemErr     R   ... 33 more

我确定 "getReadMethod()" 返回的方法对象 (m) 不为空,但 "m.invoke(obj)" 返回的对象为空。 我假设名为 "active" 的 属性 没有被 JavaEE 容器初始化(具有空值),这导致了这种情况发生。我的假设正确吗?如果不是请告诉我为什么会这样以及如何解决它。

我是 Java 的新手,如有任何建议或建议,我们将不胜感激。 此致,

让我们取消选择:

首先,我假设这段代码在您的 isActive 方法中。

m = pd[i].getReadMethod();
if(m != null) {
    getter = m.getName();              //not null
    value = m.invoke(obj).toString();  //throws NullPointerException
}

(如果不是,那么您向我们展示了错误的代码...因为堆栈跟踪清楚地表明 isActive 引发了 NPE。)

所以假设上面的评论是正确的。

  1. 我们知道 m 在语句 // not null 中不是 null,我会假设 1在下一个语句中仍然不是null

  2. 这意味着对 m.invoke(obj) 的调用不是 NPE 的原因:

    • 因为m不是null,而且
    • 因为如果 NPE 出于任何原因发生在 invoke 内部,堆栈跟踪将有所不同。
  3. 它不可能在 方法中,因为堆栈跟踪会有所不同。

因此,通过排除过程,问题一定是 invoke 正在 返回 null ... NPE 是由于 null.toString().

所以现在你需要弄清楚如何/为什么 invoke returns null,然后修复原因,或者更改你的代码以应对这种可能性。

(证据并未指出 getReadMethod 的问题。它指出您 "got" and/or 方法调用的目标对象的方法有问题。 )


1 - 如果 m 是一个字段而不是局部变量并且它对其他线程可见并且其中一个碰巧将 null 分配给恰到好处。

感谢您提出的所有建议。现在我确定 "invoke(m(obj)).toString()"(等于 "isValid().toString()") 导致 NPE 的原因是 非常简单 字段成员只是 null。

public class IntroSpectionTest {
    private String a;
    private String b;

    public IntroSpectionTest(String a, String b) {
        this.a = a;
        this.b = b;
    }
    public String getA() { return a; }
    public String getB() { return b; }

    public static void main(String[] args) {
        System.out.println(ClassInfo.getLinkedHashMap(new IntroSpectionTest(null, "String b").toString()));
    }
}

此代码导致完全相同的情况。

我只是想深入了解 WebSphere 生成的对象,而不是代码本身。如有误导,敬请见谅。