You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

非空对象抛出NullPointerException及调试源码不可见问题排查

奇怪的NullPointerException排查问题

调试应用时触发了NullPointerException,但对应的对象并非空值。此外,调试时无法查看createCopy方法的源码,已勾选编译器选项中的“Add line number attribute...”,也尝试过移除断点、清理项目等操作,但问题依旧。

异常堆栈信息

java.lang.NullPointerException
    at com.clh.model.margin.table.classes.ChMarginHeaderP.createCopy(Unknown Source)
    at com.clh.controller.builders.EccFirstCallBean.buildDefaultComponent(EccFirstCallBean.java:710)
    at com.clh.controller.builders.EccFirstCallBean.buildFirstCall(EccFirstCallBean.java:549)
    at com.clh.controller.builders.EccFirstCallBean.buildMargin(EccFirstCallBean.java:403)
    at com.clh.controller.builders.EccFirstCallBean.elabThirdLevel(EccFirstCallBean.java:268)
    at com.clh.controller.builders.EccFirstCallBeanTest.elabThirdLevelTest(EccFirstCallBeanTest.java:529)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.junit.internal.runners.TestMethod.invoke(TestMethod.java:68)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:326)
    at org.junit.internal.runners.MethodRoadie$2.run(MethodRoadie.java:89)
    at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:97)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.executeTest(PowerMockJUnit44RunnerDelegateImpl.java:310)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.executeTestInSuper(PowerMockJUnit47RunnerDelegateImpl.java:131)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.access$100(PowerMockJUnit47RunnerDelegateImpl.java:59)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner$TestExecutorStatement.evaluate(PowerMockJUnit47RunnerDelegateImpl.java:147)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.evaluateStatement(PowerMockJUnit47RunnerDelegateImpl.java:107)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.executeTest(PowerMockJUnit47RunnerDelegateImpl.java:82)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runBeforesThenTestThenAfters(PowerMockJUnit44RunnerDelegateImpl.java:298)
    at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:87)
    at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:50)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.invokeTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:218)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.runMethods(PowerMockJUnit44RunnerDelegateImpl.java:160)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$1.run(PowerMockJUnit44RunnerDelegateImpl.java:134)
    at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:34)
    at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:44)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.run(PowerMockJUnit44RunnerDelegateImpl.java:136)
    at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.run(JUnit4TestSuiteChunkerImpl.java:117)
    at org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.run(AbstractCommonPowerMockRunner.java:57)
    at org.powermock.modules.junit4.PowerMockRunner.run(PowerMockRunner.java:59)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:89)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:41)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:542)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:770)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:464)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:210)

触发异常前的变量状态

截图显示,createCopy方法中所有传入构造函数的实例字段均非空,包括chStatusTradePk、referenceDate等字段都有有效值。

createCopy方法代码

public ChMarginHeaderP createCopy() {
        final ChMarginHeaderP copyChMarginHeaderP = new ChMarginHeaderP(
                new ChMarginHeaderPPK(1), this.flgLock,this.flgIsLive, 
                this.referenceDate, this.userDescription,
                this.chCounterpartyPk,
                this.chCurrencyPk, this.chTypePk,
                this.chPortfolioPk, this.chProductsPk, this.chEntitiesPk,
                this.chStatusTradePk, this.chTypeCalledPk,this.segment, this.class_, this.section, this.division);

        return copyChMarginHeaderP;
    }

构造函数代码

public ChMarginHeaderP(final ChMarginHeaderPPK id, final boolean flgLock,
            final boolean flgLive, final Date referenceDate,
            final String userDescription, final String chCounterpartiesPk,
            final String chCurrenciesPk, final String chTypePk,
            final String chPortfolioPk, final String chProductsPk,
            final String chEntitiesPk, final String chStatusMargin,
            final String chTypeCalledPk, final String segment, 
            final String class_, final String section, final String division) {
        super();
        this.id = id;
        this.flgLock = flgLock;
        this.flgIsLive = flgLive;
        this.referenceDate = referenceDate;
        this.userDescription = userDescription;
        this.chCounterpartyPk= chCounterpartiesPk;
        this.chCurrencyPk = chCurrenciesPk;
        this.chTypePk = chTypePk;
        this.chPortfolioPk = chPortfolioPk;
        this.chProductsPk = chProductsPk;
        this.chEntitiesPk = chEntitiesPk;
        this.chStatusTradePk = chStatusMargin;
        this.chTypeCalledPk = chTypeCalledPk;
        this.segment = segment;
        this.class_ = class_;
        this.section = section; 
        this.division = division;
    }

可能的原因

  • 字节码与源码不匹配:堆栈显示Unknown Source,说明运行的字节码没有行号信息,或字节码与当前源码版本不一致。即使勾选了编译时添加行号的选项,PowerMock的字节码增强可能会破坏行号信息,导致调试时无法关联源码,且实际异常位置可能在构造函数中,但堆栈无法正确显示。
  • PowerMock字节码增强干扰:PowerMock会修改类的字节码以支持测试mock功能,可能导致对象的实际运行状态与调试器显示的不一致。比如被代理的字段在运行时实际为空,但调试器显示的是初始值;或者构造函数的参数在传递过程中被篡改,触发NPE。
  • 调试器状态不可靠:由于PowerMock使用自定义类加载器,调试器获取的变量状态可能是不准确的,看起来非空的变量在实际执行时可能为空,从而触发NullPointerException。
  • 构造函数隐式问题:虽然传入参数看起来非空,但Date类型的referenceDate如果是一个无效的引用(比如被GC回收的对象),或者字符串参数在赋值时因类加载器差异导致实际为空,都可能触发NPE。

内容的提问来源于stack exchange,提问作者Daniele Scalco

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 14:10:36