关于mina1.7及其之前版本 Exception--java.lang.OutOfMemoryError: 可能的“臭虫”

曾被和谐的博文,汗了好一阵,看了GLY的黑板报http://webmaster.iteye.com/blog/456931才明白是借说具体问题具体分析那段有似嫌,悲叹网络内容过滤此类内容水平,仅限于字眼而导致断章取义,期待更高层的过滤技术,如语义过滤~~

 同步博文 http://hi.baidu.com/fenglinquan/blog/item/afc369ee83b092f2b3fb9558.html

====================================================================

关于mina1.7及其之前版本 Exception--java.lang.OutOfMemoryError: 可能的“臭虫”
2009年08月21日 星期五 下午 12:26

 

#关于mina1.7及其之前版本 Exception in thread "OutDbThread" java.lang.OutOfMemoryError: Java heap space可能的“臭虫”

同步blog http://redsnow-fenglin.iteye.com/blog/454328

     引起OutOfMemoryError的因素可能很多,但有一点可以肯定的是和内存申请、释放有关,鉴于此,我来谈一下在做过的一个项目中,使用mina1.7遇到此问题的解决方案,下面,简单阐述一下项目出现此Exception的背景情形,以便有类似情形的朋友做个参考,找出这个相似的可能“臭虫”。
    项目中mina的主要功能是做文件传输的,也是项目的核心,下面我将分阶段来阐述“臭虫”:
    第一阶段:在项目模块测试时,系统启动内存就占去500多M,随着文件传输时间的推移,内存渐增,在数小时内增至1.2G多,之后就core掉了,问题很easy的定位在取货配送模块,即文件收发模块
    第二阶段:core掉的异常提示为OurOfMemoryError,或java heap space不足引起jvm达到hotspot,直观原因是内存申请的问题,但内存申请是mina做的啊,于是,同事经过多番尝试,终于前进了很大一步,问题暂时解决了,那么,同事做了什么事呢?两点:一点是改mina 的 seesion.write为线程处理,即在发送的时候,开辟新的短线程来完成此工作,表现效果大大提高;而是调整jvm参数,增多jvm可申请内存及jvm回收机制;
    第三阶段:该阶段是最要命的,因为已经进入了项目联调准备入网检测的阶段了,只有一周很紧的时间,core掉又跳出来了,表现形式和阶段一大致雷同,入网检测在即啊,大家忙得团团转,开会、讨论、请公司测试部门帮忙...,一时间项目被重视的高度白炽化了;下面,我先具体阐述下引起此bug的业务流程环节,以便有同样类似问题的朋友参考,然后在讲解一下我们的解决方法;
          引起bug的业务流程环节:内存的增长,只与文件发送次数成正比,而与发送文件大小无关;
          bug的解决过程:会议讨论并无结论,有的仅是各自的想法,上面的意思很简单,尽快解决问题,不影响项目入网检测,要求测试组全力协助我们开发组,测试组自然是从常规的测试入手,观察内存变化,定位引起变化的原因...,而我呢?想到内存增长与发送次数成正比,而无关文件大小,问题应该出在每次发送内存申请与释放上,会后10分钟 头 就问我是否有进展,我汗,看来头期待我能有所进展(也难怪,我是组内搞java最久的,另外几位都是为了项目而转为java),我告诉头:“还没,我在研究mina关于session.write的代码,那两个测试人员应该在做测试方面的监控”,...,先告诉大家结论:问题的确出在mina上,而其解决方法也很简单--该mina内存申请由direct方式为nod-direct方式,缩短mina池资源释放时间,具体解决过程为(问题的解决在于思路、过程,结果是附属的重要产物):
          1、优化JVM参数,治标不治本,若真的存在bug,但我们期待简单的优化可以过关,然,无果,但还是建议有兴趣的朋友看看若下几个链接,了解下JVM参数优化的问题,相信你看过之后会觉得牺牲刚才时间是值得的:
          JVM参数基础知识:http://blog.163.com/dxf_dgq_sureme/blog/static/97987377200932311451423/
                           http://jero.iteye.com/blog/75879
          JVM参数白皮书:http://java.sun.com/performance/reference/whitepapers/tuning.html#section4.2
          JVM参数优化实例,很不错的:http://topic.youkuaiyun.com/u/20081015/15/788c61e8-2773-41b6-988e-2b180f315678.html
          2、既然上面是治标非本的方法,那我们不得不另寻它方;debug模式观察到mina首先启动线程一个池类PooledByteBufferAllocator,这便成了成功解决此问题的突破口,我们看一下这个类:
public class PooledByteBufferAllocator implements ByteBufferAllocator {
    private static final int MINIMUM_CAPACITY = 1;

    private static int threadId = 0;

    private final Expirer expirer;

    private final ExpiringStack[] heapBufferStacks = new ExpiringStack[] {
            new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
            new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
            new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
            new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
            new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
            new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
            new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
            new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
            new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
            new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
            new ExpiringStack(), new ExpiringStack(), };

    private final ExpiringStack[] directBufferStacks = new ExpiringStack[] {
            new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
            new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
            new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
            new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
            new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
            new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
            new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
            new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
            new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
            new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
            new ExpiringStack(), new ExpiringStack(), };

    private int timeout;

    private boolean disposed;

    /**
     * Creates a new instance with the default timeout.
     */
    public PooledByteBufferAllocator() {
        this(60);
    }

    /**
     * Creates a new instance with the specified <tt>timeout</tt>.
     */
    public PooledByteBufferAllocator(int timeout) {
        setTimeout(timeout);
        expirer = new Expirer();
        expirer.start();
    }

    ...

    /**
     * Sets the timeout value of this allocator in seconds.
     *
     * @param timeout <tt>0</tt> or negative value to disable timeout.
     */
    public void setTimeout(int timeout) {
        if (timeout < 0) {
            timeout = 0;
        }

        this.timeout = timeout;

        if (timeout > 0) {

        }
    }

    public ByteBuffer allocate(int capacity, boolean direct) {
        ensureNotDisposed();
        UnexpandableByteBuffer ubb = allocate0(capacity, direct);
        PooledByteBuffer buf = allocateContainer();
        buf.init(ubb, true);
        return buf;
    }

    private PooledByteBuffer allocateContainer() {
        return new PooledByteBuffer();
    }
   ...
}
是可以修改默认的60(秒),调小其之,加快程序资源释放周期,但第一点在哪里呢?在类ByteBuffer.java,因为我们程序中是用ByteBuffer来分配资源的,下面是其原码:
public abstract class ByteBuffer implements Comparable<ByteBuffer> {
    private static ByteBufferAllocator allocator = new PooledByteBufferAllocator();
    /**
     * default is set true by mina
     */
    private static boolean useDirectBuffers = true;

    /**
     * Returns the current allocator which manages the allocated buffers.
     */
    public static ByteBufferAllocator getAllocator() {
        return allocator;
    }

    /**
     * Changes the current allocator with the specified one to manage
     * the allocated buffers from now.
     */
    public static void setAllocator(ByteBufferAllocator newAllocator) {
        if (newAllocator == null) {
            throw new NullPointerException("allocator");
        }

        ByteBufferAllocator oldAllocator = allocator;

        allocator = newAllocator;

        if (null != oldAllocator) {
            oldAllocator.dispose();
        }
    }

    public static boolean isUseDirectBuffers() {
        return useDirectBuffers;
    }

    public static void setUseDirectBuffers(boolean useDirectBuffers) {
        ByteBuffer.useDirectBuffers = useDirectBuffers;
    }
...
}
    从代码中我们可以看到,有用的信息是private static boolean useDirectBuffers = true;即使用直存方式申请内存,可以通过setUseDirectBuffers(boolean useDirectBuffers)方法修改其默认值
    第四阶段:问题成功解决的方法:1、修改ByteBuffer.java内存申请方式默认为对战模式;2、缩短PooledByteBufferAllocator.java对Expire处理的时长;(一种方式直接改变源代码,一种方式修改程序、调整相应参数,我采用前者,因为文件传输模块非我开放维护,不便修改代码),顺便提下:mina其实也已经意识到此问题了,在mina2.0中已经修改了内存申请的默认方式为堆栈而非直存了,而且重写了池的管理,mina2.0已不具备后兼容性了,因为变化太大了;
       经过上面的调整之后,系统启动占去内存已不足200M,在1小时内增长过两次,每次增长47M左右,之后稳定在200多M,运行24小时,表现良好,至此,问题告一段落,项目顺利通过入网检测各项指标考核,包括压力、疲劳测试;
      第五阶段:大家一定疑惑为何会有如上的解决方案,其实第四阶段是在第五阶段之后产生的,本阶段的核心是:java内存使用方式及申请方式的关系,简单说就是直存方式速度快,但资源回收在GC之外,堆栈方式速度稍逊,但资源回收在GC之内,顺便提下GC并发优于并行及其它,详细的就不自我解说了,有兴趣的朋友可以看看如下信息:
JVM 如何使用 Windows 和 Linux 上的本机内存:http://www.ibm.com/developerworks/cn/java/j-nativememory-linux/
Direct vs. non-direct buffers http://java.sun.com/j2se/1.5.0/docs/api/ ByteBuffer
apche mina关于OutOfMemoryError 的mail list :http://mail-archives.apache.org/mod_mbox/mina-dev/200611.mbox/<8C29AD40787A694A81108B3FBF4C15F1CEAF6D@hue.cybersoft-vn.com>
                                             http://mail-archives.apache.org/mod_mbox/mina-dev/200710.mbox/%3CABFD05FF09D13E4883B757E75603624DA3404A@ex-sea1.vistocorp.com%3E

似乎写的过于累赘,可能不太适合朋友们的口味,只是想阐述下具体的情况与之对应,因为Bug甚多,模式仅可借鉴非硬搬...

"C:\Program Files\Java\jdk1.8.0_191\bin\java.exe" -XX:TieredStopAtLevel=1 -noverify -Dspring.output.ansi.enabled=always -Dcom.sun.management.jmxremote -Dspring.jmx.enabled=true -Dspring.liveBeansView.mbeanDomain -Dspring.application.admin.enabled=true "-Dmanagement.endpoints.jmx.exposure.include=*" "-javaagent:D:\IDEA\IntelliJ IDEA 2023.2.8\lib\idea_rt.jar=58609:D:\IDEA\IntelliJ IDEA 2023.2.8\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_191\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\rt.jar;D:\ChromeCoreDownloads\wvp-GB28181-pro-master (1)\wvp-GB28181-pro-master\target\classes;D:\repository\org\springframework\boot\spring-boot-starter-data-redis\2.7.18\spring-boot-starter-data-redis-2.7.18.jar;D:\repository\org\springframework\boot\spring-boot-starter\2.7.18\spring-boot-starter-2.7.18.jar;D:\repository\org\springframework\boot\spring-boot-starter-logging\2.7.18\spring-boot-starter-logging-2.7.18.jar;D:\repository\ch\qos\logback\logback-classic\1.2.12\logback-classic-1.2.12.jar;D:\repository\ch\qos\logback\logback-core\1.2.12\logback-core-1.2.12.jar;D:\repository\org\apache\logging\log4j\log4j-to-slf4j\2.17.2\log4j-to-slf4j-2.17.2.jar;D:\repository\org\apache\logging\log4j\log4j-api\2.17.2\log4j-api-2.17.2.jar;D:\repository\org\slf4j\jul-to-slf4j\1.7.36\jul-to-slf4j-1.7.36.jar;D:\repository\jakarta\annotation\jakarta.annotation-api\1.3.5\jakarta.annotation-api-1.3.5.jar;D:\repository\org\yaml\snakeyaml\1.30\snakeyaml-1.30.jar;D:\repository\org\springframework\data\spring-data-redis\2.7.18\spring-data-redis-2.7.18.jar;D:\repository\org\springframework\data\spring-data-keyvalue\2.7.18\spring-data-keyvalue-2.7.18.jar;D:\repository\org\springframework\data\spring-data-commons\2.7.18\spring-data-commons-2.7.18.jar;D:\repository\org\springframework\spring-tx\5.3.31\spring-tx-5.3.31.jar;D:\repository\org\springframework\spring-oxm\5.3.31\spring-oxm-5.3.31.jar;D:\repository\io\lettuce\lettuce-core\6.1.10.RELEASE\lettuce-core-6.1.10.RELEASE.jar;D:\repository\io\netty\netty-common\4.1.101.Final\netty-common-4.1.101.Final.jar;D:\repository\io\netty\netty-handler\4.1.101.Final\netty-handler-4.1.101.Final.jar;D:\repository\io\netty\netty-resolver\4.1.101.Final\netty-resolver-4.1.101.Final.jar;D:\repository\io\netty\netty-buffer\4.1.101.Final\netty-buffer-4.1.101.Final.jar;D:\repository\io\netty\netty-transport-native-unix-common\4.1.101.Final\netty-transport-native-unix-common-4.1.101.Final.jar;D:\repository\io\netty\netty-codec\4.1.101.Final\netty-codec-4.1.101.Final.jar;D:\repository\io\netty\netty-transport\4.1.101.Final\netty-transport-4.1.101.Final.jar;D:\repository\io\projectreactor\reactor-core\3.4.34\reactor-core-3.4.34.jar;D:\repository\org\reactivestreams\reactive-streams\1.0.4\reactive-streams-1.0.4.jar;D:\repository\org\springframework\boot\spring-boot-starter-cache\2.7.18\spring-boot-starter-cache-2.7.18.jar;D:\repository\org\springframework\spring-context-support\5.3.31\spring-context-support-5.3.31.jar;D:\repository\org\springframework\spring-beans\5.3.31\spring-beans-5.3.31.jar;D:\repository\org\springframework\spring-context\5.3.31\spring-context-5.3.31.jar;D:\repository\org\springframework\boot\spring-boot-starter-web\2.7.18\spring-boot-starter-web-2.7.18.jar;D:\repository\org\springframework\boot\spring-boot-starter-json\2.7.18\spring-boot-starter-json-2.7.18.jar;D:\repository\com\fasterxml\jackson\core\jackson-databind\2.13.5\jackson-databind-2.13.5.jar;D:\repository\com\fasterxml\jackson\core\jackson-annotations\2.13.5\jackson-annotations-2.13.5.jar;D:\repository\com\fasterxml\jackson\datatype\jackson-datatype-jdk8\2.13.5\jackson-datatype-jdk8-2.13.5.jar;D:\repository\com\fasterxml\jackson\datatype\jackson-datatype-jsr310\2.13.5\jackson-datatype-jsr310-2.13.5.jar;D:\repository\com\fasterxml\jackson\module\jackson-module-parameter-names\2.13.5\jackson-module-parameter-names-2.13.5.jar;D:\repository\org\springframework\boot\spring-boot-starter-tomcat\2.7.18\spring-boot-starter-tomcat-2.7.18.jar;D:\repository\org\apache\tomcat\embed\tomcat-embed-core\9.0.83\tomcat-embed-core-9.0.83.jar;D:\repository\org\apache\tomcat\embed\tomcat-embed-el\9.0.83\tomcat-embed-el-9.0.83.jar;D:\repository\org\apache\tomcat\embed\tomcat-embed-websocket\9.0.83\tomcat-embed-websocket-9.0.83.jar;D:\repository\org\springframework\spring-web\5.3.31\spring-web-5.3.31.jar;D:\repository\org\springframework\spring-webmvc\5.3.31\spring-webmvc-5.3.31.jar;D:\repository\org\springframework\spring-expression\5.3.31\spring-expression-5.3.31.jar;D:\repository\org\springframework\boot\spring-boot-starter-websocket\2.7.18\spring-boot-starter-websocket-2.7.18.jar;D:\repository\org\springframework\spring-messaging\5.3.31\spring-messaging-5.3.31.jar;D:\repository\org\springframework\spring-websocket\5.3.31\spring-websocket-5.3.31.jar;D:\repository\org\springframework\boot\spring-boot-configuration-processor\2.7.18\spring-boot-configuration-processor-2.7.18.jar;D:\repository\org\mybatis\spring\boot\mybatis-spring-boot-starter\2.2.0\mybatis-spring-boot-starter-2.2.0.jar;D:\repository\org\mybatis\spring\boot\mybatis-spring-boot-autoconfigure\2.2.0\mybatis-spring-boot-autoconfigure-2.2.0.jar;D:\repository\org\mybatis\mybatis\3.5.7\mybatis-3.5.7.jar;D:\repository\org\mybatis\mybatis-spring\2.0.6\mybatis-spring-2.0.6.jar;D:\repository\org\springframework\boot\spring-boot-starter-security\2.7.18\spring-boot-starter-security-2.7.18.jar;D:\repository\org\springframework\spring-aop\5.3.31\spring-aop-5.3.31.jar;D:\repository\org\springframework\security\spring-security-config\5.7.11\spring-security-config-5.7.11.jar;D:\repository\org\springframework\security\spring-security-web\5.7.11\spring-security-web-5.7.11.jar;D:\repository\org\springframework\boot\spring-boot-starter-jdbc\2.7.18\spring-boot-starter-jdbc-2.7.18.jar;D:\repository\com\zaxxer\HikariCP\4.0.3\HikariCP-4.0.3.jar;D:\repository\org\springframework\spring-jdbc\5.3.31\spring-jdbc-5.3.31.jar;D:\repository\com\alibaba\druid-spring-boot-starter\1.2.23\druid-spring-boot-starter-1.2.23.jar;D:\repository\com\alibaba\druid\1.2.23\druid-1.2.23.jar;D:\repository\org\slf4j\slf4j-api\1.7.36\slf4j-api-1.7.36.jar;D:\repository\org\springframework\boot\spring-boot-autoconfigure\2.7.18\spring-boot-autoconfigure-2.7.18.jar;D:\repository\org\glassfish\jaxb\jaxb-runtime\2.3.9\jaxb-runtime-2.3.9.jar;D:\repository\org\glassfish\jaxb\txw2\2.3.9\txw2-2.3.9.jar;D:\repository\com\sun\istack\istack-commons-runtime\3.0.12\istack-commons-runtime-3.0.12.jar;D:\repository\com\sun\activation\jakarta.activation\1.2.2\jakarta.activation-1.2.2.jar;D:\repository\com\mysql\mysql-connector-j\8.2.0\mysql-connector-j-8.2.0.jar;D:\repository\org\postgresql\postgresql\42.5.1\postgresql-42.5.1.jar;D:\repository\org\checkerframework\checker-qual\3.5.0\checker-qual-3.5.0.jar;D:\ChromeCoreDownloads\wvp-GB28181-pro-master (1)\wvp-GB28181-pro-master\libs\jdbc-x86\kingbase8-8.6.0.jar;D:\repository\com\github\pagehelper\pagehelper-spring-boot-starter\1.4.6\pagehelper-spring-boot-starter-1.4.6.jar;D:\repository\com\github\pagehelper\pagehelper-spring-boot-autoconfigure\1.4.6\pagehelper-spring-boot-autoconfigure-1.4.6.jar;D:\repository\com\github\pagehelper\pagehelper\5.3.2\pagehelper-5.3.2.jar;D:\repository\com\github\jsqlparser\jsqlparser\4.5\jsqlparser-4.5.jar;D:\repository\org\springdoc\springdoc-openapi-ui\1.6.10\springdoc-openapi-ui-1.6.10.jar;D:\repository\org\springdoc\springdoc-openapi-webmvc-core\1.6.10\springdoc-openapi-webmvc-core-1.6.10.jar;D:\repository\org\webjars\swagger-ui\4.13.2\swagger-ui-4.13.2.jar;D:\repository\org\webjars\webjars-locator-core\0.50\webjars-locator-core-0.50.jar;D:\repository\com\fasterxml\jackson\core\jackson-core\2.13.5\jackson-core-2.13.5.jar;D:\repository\io\github\classgraph\classgraph\4.8.149\classgraph-4.8.149.jar;D:\repository\org\springdoc\springdoc-openapi-security\1.6.10\springdoc-openapi-security-1.6.10.jar;D:\repository\org\springdoc\springdoc-openapi-common\1.6.10\springdoc-openapi-common-1.6.10.jar;D:\repository\io\swagger\core\v3\swagger-core\2.2.2\swagger-core-2.2.2.jar;D:\repository\org\apache\commons\commons-lang3\3.12.0\commons-lang3-3.12.0.jar;D:\repository\com\fasterxml\jackson\dataformat\jackson-dataformat-yaml\2.13.5\jackson-dataformat-yaml-2.13.5.jar;D:\repository\io\swagger\core\v3\swagger-annotations\2.2.2\swagger-annotations-2.2.2.jar;D:\repository\io\swagger\core\v3\swagger-models\2.2.2\swagger-models-2.2.2.jar;D:\repository\jakarta\validation\jakarta.validation-api\2.0.2\jakarta.validation-api-2.0.2.jar;D:\repository\org\springframework\security\spring-security-core\5.7.11\spring-security-core-5.7.11.jar;D:\repository\org\springframework\security\spring-security-crypto\5.7.11\spring-security-crypto-5.7.11.jar;D:\repository\com\github\xiaoymin\knife4j-springdoc-ui\3.0.3\knife4j-springdoc-ui-3.0.3.jar;D:\repository\javax\validation\validation-api\2.0.1.Final\validation-api-2.0.1.Final.jar;D:\repository\org\springframework\boot\spring-boot-starter-aop\2.7.18\spring-boot-starter-aop-2.7.18.jar;D:\repository\org\aspectj\aspectjweaver\1.9.7\aspectjweaver-1.9.7.jar;D:\repository\javax\sip\jain-sip-ri\1.3.0-91\jain-sip-ri-1.3.0-91.jar;D:\repository\org\slf4j\log4j-over-slf4j\1.7.36\log4j-over-slf4j-1.7.36.jar;D:\repository\org\dom4j\dom4j\2.1.3\dom4j-2.1.3.jar;D:\repository\com\alibaba\fastjson2\fastjson2\2.0.57\fastjson2-2.0.57.jar;D:\repository\com\alibaba\fastjson2\fastjson2-extension\2.0.57\fastjson2-extension-2.0.57.jar;D:\repository\com\alibaba\fastjson2\fastjson2-extension-spring5\2.0.57\fastjson2-extension-spring5-2.0.57.jar;D:\repository\com\squareup\okhttp3\okhttp\4.10.0\okhttp-4.10.0.jar;D:\repository\com\squareup\okio\okio-jvm\3.0.0\okio-jvm-3.0.0.jar;D:\repository\org\jetbrains\kotlin\kotlin-stdlib-common\1.6.21\kotlin-stdlib-common-1.6.21.jar;D:\repository\org\jetbrains\kotlin\kotlin-stdlib\1.6.21\kotlin-stdlib-1.6.21.jar;D:\repository\org\jetbrains\annotations\13.0\annotations-13.0.jar;D:\repository\com\squareup\okhttp3\logging-interceptor\4.10.0\logging-interceptor-4.10.0.jar;D:\repository\org\jetbrains\kotlin\kotlin-stdlib-jdk8\1.6.21\kotlin-stdlib-jdk8-1.6.21.jar;D:\repository\org\jetbrains\kotlin\kotlin-stdlib-jdk7\1.6.21\kotlin-stdlib-jdk7-1.6.21.jar;D:\repository\io\github\rburgst\okhttp-digest\2.7\okhttp-digest-2.7.jar;D:\repository\org\bitbucket\b_c\jose4j\0.9.3\jose4j-0.9.3.jar;D:\repository\org\mitre\dsmiley\httpproxy\smiley-http-proxy-servlet\1.12.1\smiley-http-proxy-servlet-1.12.1.jar;D:\repository\org\apache\httpcomponents\httpclient\4.5.14\httpclient-4.5.14.jar;D:\repository\org\apache\httpcomponents\httpcore\4.4.16\httpcore-4.4.16.jar;D:\repository\commons-codec\commons-codec\1.15\commons-codec-1.15.jar;D:\repository\com\alibaba\easyexcel\3.3.2\easyexcel-3.3.2.jar;D:\repository\com\alibaba\easyexcel-core\3.3.2\easyexcel-core-3.3.2.jar;D:\repository\com\alibaba\easyexcel-support\3.3.2\easyexcel-support-3.3.2.jar;D:\repository\org\apache\poi\poi\4.1.2\poi-4.1.2.jar;D:\repository\org\apache\commons\commons-collections4\4.4\commons-collections4-4.4.jar;D:\repository\org\apache\commons\commons-math3\3.6.1\commons-math3-3.6.1.jar;D:\repository\com\zaxxer\SparseBitSet\1.2\SparseBitSet-1.2.jar;D:\repository\org\apache\poi\poi-ooxml\4.1.2\poi-ooxml-4.1.2.jar;D:\repository\com\github\virtuald\curvesapi\1.06\curvesapi-1.06.jar;D:\repository\org\apache\poi\poi-ooxml-schemas\4.1.2\poi-ooxml-schemas-4.1.2.jar;D:\repository\org\apache\xmlbeans\xmlbeans\3.1.0\xmlbeans-3.1.0.jar;D:\repository\org\apache\commons\commons-csv\1.8\commons-csv-1.8.jar;D:\repository\org\ehcache\ehcache\3.10.8\ehcache-3.10.8.jar;D:\repository\javax\cache\cache-api\1.1.1\cache-api-1.1.1.jar;D:\repository\commons-io\commons-io\2.11.0\commons-io-2.11.0.jar;D:\repository\org\apache\commons\commons-compress\1.24.0\commons-compress-1.24.0.jar;D:\repository\com\github\oshi\oshi-core\6.2.2\oshi-core-6.2.2.jar;D:\repository\net\java\dev\jna\jna\5.12.1\jna-5.12.1.jar;D:\repository\net\java\dev\jna\jna-platform\5.12.1\jna-platform-5.12.1.jar;D:\repository\org\springframework\session\spring-session-core\2.7.4\spring-session-core-2.7.4.jar;D:\repository\org\springframework\spring-jcl\5.3.31\spring-jcl-5.3.31.jar;D:\repository\com\google\guava\guava\32.1.3-jre\guava-32.1.3-jre.jar;D:\repository\com\google\guava\failureaccess\1.0.1\failureaccess-1.0.1.jar;D:\repository\com\google\guava\listenablefuture\9999.0-empty-to-avoid-conflict-with-guava\listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar;D:\repository\com\google\code\findbugs\jsr305\3.0.2\jsr305-3.0.2.jar;D:\repository\com\google\errorprone\error_prone_annotations\2.21.1\error_prone_annotations-2.21.1.jar;D:\repository\com\google\j2objc\j2objc-annotations\2.8\j2objc-annotations-2.8.jar;D:\repository\org\apache\ftpserver\ftpserver-core\1.2.0\ftpserver-core-1.2.0.jar;D:\repository\org\apache\mina\mina-core\2.1.6\mina-core-2.1.6.jar;D:\repository\org\apache\ftpserver\ftplet-api\1.2.0\ftplet-api-1.2.0.jar;D:\repository\org\projectlombok\lombok\1.18.30\lombok-1.18.30.jar;D:\repository\io\github\sevdokimov\logviewer\log-viewer-spring-boot\1.0.10\log-viewer-spring-boot-1.0.10.jar;D:\repository\org\springframework\boot\spring-boot\2.7.18\spring-boot-2.7.18.jar;D:\repository\io\github\sevdokimov\logviewer\log-viewer\1.0.10\log-viewer-1.0.10.jar;D:\repository\io\github\sevdokimov\logviewer\log-viewer-frontend\1.0.10\log-viewer-frontend-1.0.10.jar;D:\repository\com\google\code\gson\gson\2.9.1\gson-2.9.1.jar;D:\repository\com\github\ben-manes\caffeine\caffeine\2.9.3\caffeine-2.9.3.jar;D:\repository\com\typesafe\config\1.3.3\config-1.3.3.jar;D:\repository\org\mozilla\rhino\1.7.13\rhino-1.7.13.jar;D:\repository\jakarta\xml\bind\jakarta.xml.bind-api\2.3.3\jakarta.xml.bind-api-2.3.3.jar;D:\repository\jakarta\activation\jakarta.activation-api\1.2.2\jakarta.activation-api-1.2.2.jar;D:\repository\org\springframework\spring-core\5.3.31\spring-core-5.3.31.jar" com.genersoft.iot.vmp.VManageBootstrap ___ __ ___ ___ ________ ________ ________ ________ |\ \ |\ \|\ \ / /|\ __ \ |\ __ \|\ __ \|\ __ \ \ \ \ \ \ \ \ \ / / | \ \|\ \ ____________\ \ \|\ \ \ \|\ \ \ \|\ \ \ \ \ __\ \ \ \ \/ / / \ \ ____\\____________\ \ ____\ \ _ _\ \ \\\ \ \ \ \|\__\_\ \ \ / / \ \ \___\|____________|\ \ \___|\ \ \\ \\ \ \\\ \ \ \____________\ \__/ / \ \__\ \ \__\ \ \__\\ _\\ \_______\ \|____________|\|__|/ \|__| \|__| \|__|\|__|\|_______| 2025-08-21 16:01:04.159 [main] INFO --- com.genersoft.iot.vmp.VManageBootstrap: 55 Starting VManageBootstrap using Java 1.8.0_131 on DESKTOP-UF2P6NE with PID 174620 (D:\ChromeCoreDownloads\wvp-GB28181-pro-master (1)\wvp-GB28181-pro-master\target\classes started by lenovo in D:\ChromeCoreDownloads\wvp-GB28181-pro-master (1)\wvp-GB28181-pro-master) 2025-08-21 16:01:04.163 [main] INFO --- com.genersoft.iot.vmp.VManageBootstrap: 638 The following 1 profile is active: "274-dev" 2025-08-21 16:01:05.021 [main] INFO --- o.s.context.annotation.ConfigurationClassParser: 471 Properties location [classpath:git.properties] not resolvable: class path resource [git.properties] cannot be opened because it does not exist 2025-08-21 16:01:05.687 [main] INFO --- o.s.d.r.config.RepositoryConfigurationDelegate: 262 Multiple Spring Data modules found, entering strict repository configuration mode 2025-08-21 16:01:05.689 [main] INFO --- o.s.d.r.config.RepositoryConfigurationDelegate: 132 Bootstrapping Spring Data Redis repositories in DEFAULT mode. 2025-08-21 16:01:05.807 [main] INFO --- o.s.d.r.config.RepositoryConfigurationDelegate: 201 Finished Spring Data repository scanning in 107 ms. Found 0 Redis repository interfaces. 2025-08-21 16:01:06.525 [main] INFO --- o.s.boot.web.embedded.tomcat.TomcatWebServer: 108 Tomcat initialized with port(s): 8080 (http) 2025-08-21 16:01:06.535 [main] INFO --- org.apache.coyote.http11.Http11NioProtocol: 173 Initializing ProtocolHandler ["http-nio-8080"] 2025-08-21 16:01:06.537 [main] INFO --- org.apache.catalina.core.StandardService: 173 Starting service [Tomcat] 2025-08-21 16:01:06.537 [main] INFO --- org.apache.catalina.core.StandardEngine: 173 Starting Servlet engine: [Apache Tomcat/9.0.83] 2025-08-21 16:01:06.797 [main] INFO --- o.a.c.core.ContainerBase.[Tomcat].[localhost].[/]: 173 Initializing Spring embedded WebApplicationContext 2025-08-21 16:01:06.797 [main] INFO --- o.s.b.w.s.c.ServletWebServerApplicationContext: 292 Root WebApplicationContext: initialization completed in 2595 ms 2025-08-21 16:01:07.117 [main] INFO --- c.a.d.s.b.a.DruidDataSourceAutoConfigure: 68 Init DruidDataSource 2025-08-21 16:01:07.235 [main] ERROR --- o.s.boot.web.embedded.tomcat.TomcatStarter: 61 Error starting Tomcat context. Exception: org.springframework.beans.factory.UnsatisfiedDependencyException. Message: Error creating bean with name 'proxyServletConfig': Unsatisfied dependency expressed through field 'mediaServerService'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'mediaServerServiceImpl': Unsatisfied dependency expressed through field 'mediaServerMapper'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'mediaServerMapper' defined in file [D:\ChromeCoreDownloads\wvp-GB28181-pro-master (1)\wvp-GB28181-pro-master\target\classes\com\genersoft\iot\vmp\storager\dao\MediaServerMapper.class]: Unsatisfied dependency expressed through bean property 'sqlSessionFactory'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'sqlSessionFactory' defined in class path resource [com/genersoft/iot/vmp/conf/MybatisConfig.class]: Unsatisfied dependency expressed through method 'sqlSessionFactory' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource' defined in class path resource [com/alibaba/druid/spring/boot/autoconfigure/DruidDataSourceAutoConfigure.class]: Invocation of init method failed; nested exception is org.springframework.boot.autoconfigure.jdbc.DataSourceProperties$DataSourceBeanCreationException: Failed to determine a suitable driver class 2025-08-21 16:01:07.255 [main] INFO --- org.apache.catalina.core.StandardService: 173 Stopping service [Tomcat] 2025-08-21 16:01:07.268 [main] WARN --- org.apache.catalina.loader.WebappClassLoaderBase: 173 The web application [ROOT] appears to have started a thread named [lettuce-timer-3-1] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread: java.lang.Thread.sleep(Native Method) io.netty.util.HashedWheelTimer$Worker.waitForNextTick(HashedWheelTimer.java:600) io.netty.util.HashedWheelTimer$Worker.run(HashedWheelTimer.java:496) io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) java.lang.Thread.run(Thread.java:748) 2025-08-21 16:01:07.269 [main] WARN --- o.s.b.w.s.c.AnnotationConfigServletWebServerApplicationContext: 599 Exception encountered during context initialization - cancelling refresh attempt: org.springframework.context.ApplicationContextException: Unable to start web server; nested exception is org.springframework.boot.web.server.WebServerException: Unable to start embedded Tomcat 2025-08-21 16:01:07.287 [main] INFO --- o.s.b.a.l.ConditionEvaluationReportLoggingListener: 136 Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled. 2025-08-21 16:01:07.301 [main] ERROR --- o.s.b.diagnostics.LoggingFailureAnalysisReporter: 40 *************************** APPLICATION FAILED TO START *************************** Description: Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured. Reason: Failed to determine a suitable driver class Action: Consider the following: If you want an embedded database (H2, HSQL or Derby), please put it on the classpath. If you have database settings to be loaded from a particular profile you may need to activate it (the profiles 274-dev are currently active). Process finished with exit code 1 分析错误
最新发布
08-22
<think>我们正在处理一个Spring Boot应用启动失败的问题,错误信息是:"Failed to determine a suitable driver class"。这通常发生在Spring Boot无法自动配置数据源(DataSource)时。根据引用[1]和引用[2],我们可以分析以下可能的原因和解决方案。 ### 问题分析 1. **缺少数据库驱动依赖**:Spring Boot需要相应的数据库驱动来连接数据库。例如,使用MySQL需要添加`mysql-connector-java`依赖。 2. **数据源配置错误**:在`application.properties`或`application.yml`中,数据源配置(如`spring.datasource.url`)可能缺失或格式不正确。 3. **Spring Boot版本与依赖不兼容**:特别是对于Spring Boot 3.x,一些依赖需要特定版本或使用`spring-boot3-starter`(如引用[2]提到的动态数据源依赖需要`dynamic-datasource-spring-boot3-starter`)。 4. **依赖冲突**:可能存在多个数据源依赖冲突,导致自动配置失败。 ### 解决方案 #### 1. 检查数据库驱动依赖 确保在`pom.xml`(Maven)或`build.gradle`(Gradle)中添加了正确的数据库驱动。例如,对于MySQL: ```xml <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.28</version> <!-- 请使用适合你数据库版本的驱动 --> </dependency> ``` #### 2. 检查数据源配置 在`application.properties`中,确保配置了数据源URL、用户名和密码: ```properties spring.datasource.url=jdbc:mysql://localhost:3306/mydb?useSSL=false&serverTimezone=UTC spring.datasource.username=root spring.datasource.password=root spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver ``` #### 3. 检查Spring Boot版本与依赖兼容性 - 如果你使用的是Spring Boot 2.7.x,确保依赖的版本兼容。例如,动态数据源依赖应为`dynamic-datasource-spring-boot-starter`(不带`3`)。 - 对于Spring Boot 3.x,必须使用支持Spring Boot 3的依赖,如引用[2]所示:`dynamic-datasource-spring-boot3-starter`。 #### 4. 排除自动配置(可选) 如果项目不需要数据库,可以在启动类上排除数据源自动配置: ```java @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class}) public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } } ``` #### 5. 检查依赖冲突 使用`mvn dependency:tree`或`gradle dependencies`命令检查依赖树,排除重复或冲突的依赖。 ### 总结 根据错误信息"Failed to determine a suitable driver class",重点检查数据库驱动依赖和数据源配置。同时,注意Spring Boot版本与依赖的兼容性。按照上述步骤排查,通常可以解决问题。 §§相关问题§§ 1. 如何解决Spring Boot中`DataSource`配置失败的问题? 2. Spring Boot 2.x和3.x在数据源配置上有哪些主要区别? 3. 如何在Spring Boot中配置多数据源?</think>### Spring Boot数据源配置错误分析 您遇到的错误信息`Failed to determine a suitable driver class`通常发生在Spring Boot无法自动配置数据源时。以下是详细分析和解决方案: #### 核心问题原因 1. **驱动类未识别**:Spring Boot无法自动检测到合适的JDBC驱动类 2. **配置缺失**:数据源URL未在配置文件中指定(如`application.properties`) 3. **依赖问题**:缺少数据库驱动依赖或版本不兼容 4. **Spring Boot版本兼容性**:如引用[2]指出,Spring Boot 3.x需要特定格式的依赖命名 #### 解决方案步骤 1. **检查依赖配置**(关键步骤) 在`pom.xml`中添加数据库驱动依赖(以MySQL为例): ```xml <!-- Spring Boot 2.7.x 适用 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.33</version> </dependency> ``` 2. **配置数据源属性** 在`application.properties`中添加: ```properties spring.datasource.url=jdbc:mysql://localhost:3306/yourdb spring.datasource.username=root spring.datasource.password=yourpassword # 明确指定驱动类(可选但推荐) spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver ``` 3. **检查自动配置** 确保未禁用数据源自动配置: ```java @SpringBootApplication public class YourApplication { ... } // 不要排除DataSourceAutoConfiguration ``` 4. **Spring Boot 3.x特殊处理**(如适用) 如引用[2]所述,Spring Boot 3需要特定依赖命名: ```xml <!-- Spring Boot 3.x 必须使用boot3-starter --> <dependency> <groupId>com.baomidou</groupId> <artifactId>dynamic-datasource-spring-boot3-starter</artifactId> <version>${dynamic-ds.version}</version> </dependency> ``` #### 常见错误排查 - 🔍 检查依赖树:`mvn dependency:tree` 确认驱动是否存在 - 🔍 验证配置文件位置:确保`application.properties`在`src/main/resources`下 - 🔍 检查数据库服务状态:确认数据库实例正在运行 - 🔍 版本兼容性:Spring Boot 2.7.x建议使用MySQL驱动8.0.x版本 #### 解决方案验证 成功配置后,启动日志应显示类似信息: ``` Initializing DataSource with URL: jdbc:mysql://localhost:3306/yourdb ``` ### 相关问题 1. 如何解决Spring Boot 3中`dynamic-datasource`找不到数据源的问题?[^2] 2. Spring Boot 2.x和3.x在数据源自动配置上有哪些主要区别? 3. 如何手动配置多数据源而不使用自动配置? 4. 当使用非关系型数据库(如MongoDB)时如何避免数据源配置错误? [^1]: 数据库配置未生效的典型错误信息 [^2]: Spring Boot 3中数据源依赖的特殊要求
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值