Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

服务首次启动,并发场景下,偶发NPE异常 #742

Closed
1 task done
homawu opened this issue May 4, 2023 · 2 comments
Closed
1 task done

服务首次启动,并发场景下,偶发NPE异常 #742

homawu opened this issue May 4, 2023 · 2 comments

Comments

@homawu
Copy link

homawu commented May 4, 2023

  • 我已在 issues 搜索类似问题,并且不存在相同的问题.

异常模板

使用环境

  • PageHelper 版本: 5.1.10
  • 数据库类型和版本: 5.7.26-30102-log
  • JDBC_URL: jdbc:mysql://xx.xx.xx:3306/xxdb?characterEncoding=UTF8&socketTimeout=60000&allowMultiQueries=true

完整异常信息

[Encrypt]【查询员工信息】param:{"type":"id","ids":[2481818508],"entId":5472009}
org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.exceptions.PersistenceException: 
### Error querying database.  Cause: java.lang.NullPointerException
### Cause: java.lang.NullPointerException
at org.mybatis.spring.MyBatisExceptionTranslator.translateExceptionIfPossible(MyBatisExceptionTranslator.java:77)
at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:446)
at com.sun.proxy.$Proxy185.selectList(Unknown Source)
at org.mybatis.spring.SqlSessionTemplate.selectList(SqlSessionTemplate.java:230)
at org.apache.ibatis.binding.MapperMethod.executeForMany(MapperMethod.java:139)
at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:76)
at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:59)
at com.sun.proxy.$Proxy191.queryByCondition(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.xxx.dao.AsyncMapperProxy.invoke(AsyncMapperProxy.java:67)
at com.sun.proxy.$Proxy191.queryByCondition(Unknown Source)
at com.xxx.yyy.service.inner.impl.EmployInfoServiceImpl.queryByCondition(EmployInfoServiceImpl.java:346)
at com.xxx.yyy.service.inner.impl.EmployInfoServiceImpl$$FastClassBySpringCGLIB$$3f507d61.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:736)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:671)
at com.xxx.yyy.service.inner.impl.EmployInfoServiceImpl$$EnhancerBySpringCGLIB$$50a1d81a.queryByCondition(<generated>)
at com.xxx.yyy.server.thrift.EmployInfoThriftServiceImpl.queryByCondition(EmployInfoThriftServiceImpl.java:444)
at com.xxx.yyy.server.thrift.EmployInfoThriftServiceImpl$$FastClassBySpringCGLIB$$87624c37.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:736)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:671)
at com.xxx.yyy.server.thrift.EmployInfoThriftServiceImpl$$EnhancerBySpringCGLIB$$587ebeef.queryByCondition(<generated>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.xxx.service.mobile.thrift.proxy.ThriftServerInvoker.doInvoke(ThriftServerInvoker.java:363)
at com.xxx.service.mobile.thrift.proxy.ThriftServerInvoker$1.handle(ThriftServerInvoker.java:389)
at com.xxx.service.mobile.thrift.server.filter.AccessLogFilter.filter(AccessLogFilter.java:39)
at com.xxx.dorado.rpc.handler.filter.InvokeChainBuilder$2.handle(InvokeChainBuilder.java:106)
at com.xxx.service.mobile.thrift.server.filter.ServerRhinoLimiterFilter.filter(ServerRhinoLimiterFilter.java:73)
at com.xxx.dorado.rpc.handler.filter.InvokeChainBuilder$2.handle(InvokeChainBuilder.java:106)
at com.xxx.service.mobile.thrift.proxy.ThriftServerInvoker.invoke(ThriftServerInvoker.java:304)
at com.sun.proxy.$Proxy285.queryByCondition(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.xxx.service.mobile.thrift.annotation.ThriftMethodProcessor.invokeMethod(ThriftMethodProcessor.java:174)
at com.xxx.service.mobile.thrift.annotation.ThriftMethodProcessor.process(ThriftMethodProcessor.java:138)
at com.xxx.service.mobile.thrift.proxy.ThriftServerPublisher$ThriftServiceProcessor.process(ThriftServerPublisher.java:642)
at com.xxx.service.mobile.thrift.server.netty.DefaultServerHandler.handleRequest(DefaultServerHandler.java:273)
at com.xxx.service.mobile.thrift.server.netty.DefaultServerHandler$1.run(DefaultServerHandler.java:164)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Caused by: org.apache.ibatis.exceptions.PersistenceException: 
### Error querying database.  Cause: java.lang.NullPointerException
### Cause: java.lang.NullPointerException
at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:30)
at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:150)
at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:141)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:433)
... 54 more
Caused by: java.lang.NullPointerException
at com.github.pagehelper.PageHelper.afterAll(PageHelper.java:118)
at com.github.pagehelper.PageInterceptor.intercept(PageInterceptor.java:113)
at org.apache.ibatis.plugin.Plugin.invoke(Plugin.java:61)
at com.sun.proxy.$Proxy337.query(Unknown Source)
at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:148)
... 60 more

原因

PageInterceptor类对象里面会初始化PageHelper(对应变量dialect);
PageHelper类对象里面会初始化PageAutoDialect(对应变量autoDialect);

1.由于采用的都是单例模式,服务启动时,假定有2个线程进入分页查询场景,分别是线程A和B;
2.当线程A执行至初始化完PageHelper(dialect变量不为null),而PageHelper类尚未初始化完成(对应autoDialect变量);
3.线程B执行至以下代码时,由于dialect不为null,所以跳过,执行后续业务逻辑;

private void checkDialectExists() {
        if (dialect == null) {
            synchronized (default_dialect_class) {
                if (dialect == null) {
                    setProperties(new Properties());
                }
            }
        }
    }

4.当线程B执行至dialect.afterAll();这里,但线程A尚未初始化完PageHelper类时,就会出现NPE异常

功能建议

确保pageHelper.autoDialect变量初始化成功

private void checkDialectExists() {
        if (dialect == null || pageHelper.autoDialect == null) {
            synchronized (default_dialect_class) {
                if (dialect == null || pageHelper.autoDialect == null {
                    setProperties(new Properties());
                }
            }
        }
    }
@abel533
Copy link
Collaborator

abel533 commented May 4, 2023

试过最新版本吗?

@homawu
Copy link
Author

homawu commented May 5, 2023

试过,并且看了一下最新代码checkDialectExists这一段和5.1.10版本一致。这个问题,只有首次启动并且是并发场景才可能发生,我们的服务增加了每天定时扩缩容之后,出现过2次。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants