our project has about 10 SpingBoot module, we use maven to manage dependencies. 10 jar size about 2G. recently we need to reduce the jar size convenient for our customer deploy.
I got an idea, extract common jar(no very often change), such as spring-.jar, spring-boot-.jar, jodd*.jar, elasticsearch etc. As long as >= 2 project use one same dependence, the one we called "common jar".
If u know some useful solutions, please tell me.
I have tried under method, but met some troubles.
New a program as tool to calculate common artifactId between my projects, finally I got a artifactId list.
New a maven module to package common dependencies, finally I got a lib document contains common jar files. I named it "common-lib".
Change old project's pom file as follows:
- add maven-jar-plugin to let my project load the common lib's classes
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>com.xx.MyManagerApplication</mainClass>
<useUniqueVersions>false</useUniqueVersions>
<addClasspath>true</addClasspath>
<!--classpathPrefix let Manifest.MF's Class-Path add the 'common-lib' as prefix-->
<classpathPrefix>common-lib/</classpathPrefix>
</manifest>
<manifestEntries>
<Class-Path>.</Class-Path>
</manifestEntries>
</archive>
</configuration>
</plugin>
- Change spring-boot-maven-plugin's configuration as fllows:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>com.xx.MyManagerApplication</mainClass>
<layout>ZIP</layout>
<excludeArtifactIds>
spring-webmvc,
spring-web,
spring-tx,
spring-security-rsa,
spring-security-crypto,
spring-jdbc,
spring-jcl,
spring-expression,
spring-core,
spring-context,
spring-cloud-starter-zipkin,
...ellipsis
</excludeArtifactIds>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
finally my project's jar lib only contains none common-lib. and the jar size reduce to 900K(105M in the past). It greatly reduce the jar size.
- Placed the myproject.jar and common-lib under the same directory
- common-lib
- many jars...
- myproject.jar
Then start up my project
java -Dspring.profiles.active=dev -Dspring.config.location=application.yml -jar my-project.jar
However it did not work as I dreamd. instead with a error message show in the console
[2020-12-01 15:54:19.252+0800]-[foundation-manager]-[1;31m[ERROR][0;39m-[]-[8340:main] o.s.boot.SpringApplication 837 : Application run failed
java.lang.NoClassDefFoundError: groovy/lang/GroovyObject
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:467)
at java.net.URLClassLoader.access$100(URLClassLoader.java:73)
at java.net.URLClassLoader$1.run(URLClassLoader.java:368)
at java.net.URLClassLoader$1.run(URLClassLoader.java:362)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:361)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:338)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at org.springframework.boot.BeanDefinitionLoader.<init>(BeanDefinitionLoader.java:84)
at org.springframework.boot.SpringApplication.createBeanDefinitionLoader(SpringApplication.java:745)
at org.springframework.boot.SpringApplication.load(SpringApplication.java:685)
at org.springframework.boot.SpringApplication.prepareContext(SpringApplication.java:381)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:305)
at org.springframework.boot.builder.SpringApplicationBuilder.run(SpringApplicationBuilder.java:137)
at org.springframework.cloud.bootstrap.BootstrapApplicationListener.bootstrapServiceContext(BootstrapApplicationListener.java:208)
at org.springframework.cloud.bootstrap.BootstrapApplicationListener.onApplicationEvent(BootstrapApplicationListener.java:104)
at org.springframework.cloud.bootstrap.BootstrapApplicationListener.onApplicationEvent(BootstrapApplicationListener.java:70)
at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:172)
at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:165)
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139)
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:127)
at org.springframework.boot.context.event.EventPublishingRunListener.environmentPrepared(EventPublishingRunListener.java:74)
at org.springframework.boot.SpringApplicationRunListeners.environmentPrepared(SpringApplicationRunListeners.java:54)
at org.springframework.boot.SpringApplication.prepareEnvironment(SpringApplication.java:338)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:297)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1242)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1230)
at com.yealink.foundation.manager.app.FoundationManagerApplication.main(FoundationManagerApplication.java:44)
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:498)
at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:48)
at org.springframework.boot.loader.Launcher.launch(Launcher.java:87)
at org.springframework.boot.loader.Launcher.launch(Launcher.java:50)
at org.springframework.boot.loader.PropertiesLauncher.main(PropertiesLauncher.java:593)
Caused by: java.lang.ClassNotFoundException: groovy.lang.GroovyObject
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:338)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 40 common frames omitted
groovy's lib is not common-lib, it exist in the project's jar. the reason is the step 2 I changed the Manifest.MF file so jvm find the groovy's lib in the common-lib/groovy.xxx.jar ?
If u know some useful solutions, please tell me.