如何 运行 spring 用最少的内存启动 fat jar?

How to run spring boot fat jar with minimal memory?

这是我们的 Maven MediSpan 项目。实际上它是一个 REST 网络服务。它的 return JSON 对象用于通过 GPI 代码查询特定患者的药物药物相互作用。这是一个剩余查询的示例:

http://localhost:8017/mspn/query?pid=1000&
gpis=83-20-00-30-20-03-10&gpis=64-99-10-02-12-03-20

这是我们项目的结构:

/opt/java/spring/boot/fat/jar/project/chorke─mspn─server/
    ├─ MediSpan.Documents.Monograph.css                   [     1,697 Byte]
    ├─ MediSpan.Documents.Monograph.xslt                  [    35,167 Byte]
    ├─ bitronix-tx-mgr-log-001                            [ 2,097,173 Byte]
    ├─ bitronix-tx-mgr-log-002                            [ 2,097,173 Byte]
    └─ chorke─mspn─server.jar!                            [26,022,610 Byte]
        ├─ medispan/                                      [   443,756 Byte]
        ├─ META-INF/                                      [    33,702 Byte]
        ├─ org/springframework/boot/loader/               [   165,003 Byte]
        ├─ com/chorke/                                    [    27,633 Byte]
        ├─ application.properties                         [       501 Byte]
        ├─ application.yml                                [     2,234 Byte]
        ├─ MediSpan.Foundation.Config.xml                 [    14,939 Byte]
        ├─ MediSpan.Foundation.Text.xml                   [     9,003 Byte]
        ├─ log4j.xml                                      [     2,254 Byte]
        └─ lib/                                           [25,688,056 Byte]
            ├─ aopalliance-1.0.jar
            ├─ btm-2.1.4.jar
            ├─ c3p0-0.9.1.2.jar
            ├─ camel-core-2.15.2.jar
            ├─ camel-jasypt-2.15.2.jar
            ├─ camel-quartz2-2.15.2.jar
            ├─ camel-spring-2.15.2.jar
            ├─ camel-spring-javaconfig-2.15.2.jar
            ├─ chorke-comn-spring-2.0.00-SNAPSHOT.jar     [    11,698 Byte]
            ├─ chorke-mspn-entity-2.0.00-SNAPSHOT.jar     [    13,486 Byte]
            ├─ chorke-mspn-parser-2.0.00-SNAPSHOT.jar     [    15,921 Byte]
            ├─ chorke-mspn-persis-2.0.00-SNAPSHOT.jar     [    23,328 Byte]
            ├─ chorke-mspn-utlity-2.0.00-SNAPSHOT.jar     [    25,684 Byte]
            ├─ commons-lang3-3.3.2.jar
            ├─ commons-logging-1.1.1.jar
            ├─ ehcache-core-2.6.11.jar
            ├─ jackson-annotations-2.4.6.jar
            ├─ jackson-core-2.4.6.jar
            ├─ jackson-databind-2.4.6.jar
            ├─ jasypt-1.9.2.jar
            ├─ javax.transaction-api-1.2.jar
            ├─ jaxb-core-2.2.11.jar
            ├─ jaxb-impl-2.2.11.jar
            ├─ log4j-1.2.17.jar
            ├─ medispan-business-5.1.10.jar
            ├─ medispan-concepts-5.1.10.jar
            ├─ medispan-conditions-5.1.10.jar
            ├─ medispan-documents-5.1.10.jar
            ├─ medispan-interactions-5.1.10.jar
            ├─ medispan-screening-5.1.10.jar
            ├─ medispan-utility-5.1.10.jar
            ├─ mybatis-3.2.8.jar
            ├─ mybatis-ehcache-1.0.2.jar
            ├─ mybatis-spring-1.2.2.jar
            ├─ ojdbc6-11.2.0.3.jar
            ├─ org.apache.servicemix.bundles.cglib-2.1_3_7.jar
            ├─ quartz-2.2.1.jar
            ├─ slf4j-api-1.7.12.jar
            ├─ slf4j-log4j12-1.7.12.jar
            ├─ snakeyaml-1.14.jar
            ├─ spring-aop-4.1.6.RELEASE.jar
            ├─ spring-beans-4.1.6.RELEASE.jar
            ├─ spring-boot-1.2.4.RELEASE.jar
            ├─ spring-boot-actuator-1.2.4.RELEASE.jar
            ├─ spring-boot-autoconfigure-1.2.4.RELEASE.jar
            ├─ spring-boot-starter-1.2.4.RELEASE.jar
            ├─ spring-boot-starter-actuator-1.2.4.RELEASE.jar
            ├─ spring-boot-starter-tomcat-1.2.4.RELEASE.jar
            ├─ spring-context-4.1.6.RELEASE.jar
            ├─ spring-context-support-4.1.6.RELEASE.jar
            ├─ spring-core-4.1.6.RELEASE.jar
            ├─ spring-expression-4.1.6.RELEASE.jar
            ├─ spring-jdbc-4.1.6.RELEASE.jar
            ├─ spring-jms-4.1.6.RELEASE.jar
            ├─ spring-messaging-4.1.6.RELEASE.jar
            ├─ spring-tx-4.1.6.RELEASE.jar
            ├─ spring-web-4.1.6.RELEASE.jar
            ├─ spring-webmvc-4.1.6.RELEASE.jar
            ├─ tomcat-embed-core-8.0.23.jar
            ├─ tomcat-embed-el-8.0.23.jar
            ├─ tomcat-embed-logging-juli-8.0.23.jar
            └─ tomcat-embed-websocket-8.0.23.jar

这是 运行ning 这个 fat jar 项目及其矩阵的命令:

# without setting java option
java -jar chorke-mspn-server.jar

在 41.824 秒内启动了 BootstrapApplication(JVM 运行ning 为 42.807)

工作正常。

# setting java option for 1024 MB
java -Xmx1024M -XX:MaxPermSize=768M -XX:+CMSClassUnloadingEnabled \
-jar chorke-mspn-server.jar

在 42.134 秒内启动了 BootstrapApplication(JVM 运行ning 为 43.084)

工作正常。

# setting java option for 512 MB
java -Xmx512M -XX:MaxPermSize=384M -XX:+CMSClassUnloadingEnabled \
-jar chorke-mspn-server.jar

在 42.385 秒内启动了 BootstrapApplication(JVM 运行ning 为 43.358)

工作正常。

# setting java option for 256 MB
java -Xmx256M -XX:MaxPermSize=192M -XX:+CMSClassUnloadingEnabled \
-jar chorke-mspn-server.jar

在 42.202 秒内启动了 BootstrapApplication(JVM 运行ning 为 43.174)

抛出异常[Handler处理失败;嵌套异常是 java.lang.OutOfMemoryError:超出 GC 开销限制],根本原因是

java.lang.OutOfMemoryError: GC overhead limit exceeded
        at java.lang.Integer.valueOf(Integer.java:642)
        at medispan.foundation.convert.ValueType.asValue(Unknown Source)
        at medispan.foundation.dataaccess.providers.sql.SQLProvider.executeForResults(Unknown Source)
        at medispan.foundation.dataaccess.providers.sql.SQLDataAccessProvider.innerExecuteForCollection(Unknown Source)
        at medispan.foundation.dataaccess.DataAccessProvider.executeForCollection(Unknown Source)
        at medispan.business.dataaccess.BusinessDataAccessManager.load(Unknown Source)
        at medispan.business.dataaccess.QueryPropertyValues.getPropertyValue(Unknown Source)
        at medispan.business.dataaccess.QueryPropertyValues.getInnerValue(Unknown Source)
        more..

此应用程序包含嵌入式tomcat服务器spring引导spring mvc, myBatis, apache-camel, bitronix 事务管理器 , 医疗。我们希望 运行 它在 32~128 MB 内存中。您能否建议我们 运行 将此应用程序与内存使用 optimal/minimal 结合起来?

您需要 运行 像 JProfile 或 VisualVM 这样的 Profiler 来查看消耗内存的内容。

我可以马上告诉你,你永远不会把所有这些额外的库都降到 32MB。仅 Apache Camel 就可能需要至少 256MB 才能可靠地 运行。 Apache Camel 不应该嵌入到微服务中。这是您的服务应该从外部调用的服务。此外,使用 JPA 或几乎任何缓存都会使内存使用率变得如此低。

我在 Spring 引导中确实有一些大容量的微服务 运行 只有 32MB - 64MB,但它们基本上只是做一些计算。所有这些额外的库和服务将大大扩展您的内存使用量。