文章目录

jre的运行时主要jar文件rt.jar都很大,这导致了用java做的桌面客户端程序很难发布绑定jre发布。这在很大程度上限制了java桌面软件的分发。可是,jre并不是在所有的用户计算机上都有安装,即使安装了,也未必我们期望的版本。因此,对jre做精简,减少体积是有必要的。

减少jre体积的办法主要是,将程序用到过的类打包进发布版本中,将不需要的类剔除出发布版中。获取java程序所依赖的类可以通过在运行程序时选择jvm参数-XX:+TraceClassLoading来获取,在eclipse中可以如下图设置

运行输出结果很长,贴开头和结尾的部分输出如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[Opened /home/program/jdk1.8.0/jre/lib/rt.jar]
[Loaded java.lang.Object from /home/program/jdk1.8.0/jre/lib/rt.jar]
[Loaded java.io.Serializable from /home/program/jdk1.8.0/jre/lib/rt.jar]
[Loaded java.lang.Comparable from /home/program/jdk1.8.0/jre/lib/rt.jar]
[Loaded java.lang.CharSequence from /home/program/jdk1.8.0/jre/lib/rt.jar]
[Loaded java.lang.String from /home/program/jdk1.8.0/jre/lib/rt.jar]
[Loaded java.lang.reflect.AnnotatedElement from /home/program/jdk1.8.0/jre/lib/rt.jar]
[Loaded java.lang.reflect.GenericDeclaration from /home/program/jdk1.8.0/jre/lib/rt.jar]
[Loaded java.lang.reflect.Type from /home/program/jdk1.8.0/jre/lib/rt.jar]
......
[Loaded sun.misc.FloatingDecimal$BinaryToASCIIBuffer from /home/program/jdk1.8.0/jre/lib/rt.jar]
[Loaded sun.misc.FloatingDecimal$1 from /home/program/jdk1.8.0/jre/lib/rt.jar]
[Loaded sun.misc.FloatingDecimal$ASCIIToBinaryConverter from /home/program/jdk1.8.0/jre/lib/rt.jar]
[Loaded sun.misc.FloatingDecimal$PreparedASCIIToBinaryBuffer from /home/program/jdk1.8.0/jre/lib/rt.jar]
[Loaded sun.misc.FDBigInteger from /home/program/jdk1.8.0/jre/lib/rt.jar]
-9.0
Problem3
100.2
01000010110010000110011001100110
[Loaded java.lang.Shutdown from /home/program/jdk1.8.0/jre/lib/rt.jar]
[Loaded java.lang.Shutdown$Lock from /home/program/jdk1.8.0/jre/lib/rt.jar]

以Loaded开头的就是jvm自动加载的类,将输出重定向到文件中,用grep、awk、sort可以筛选出类名和所在文件,如下,同样只贴开头和结尾的部分输出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
$ cat jvmload.txt | grep '^\[Loaded*'
[Loaded java.lang.Object from /home/program/jdk1.8.0/jre/lib/rt.jar]
[Loaded java.io.Serializable from /home/program/jdk1.8.0/jre/lib/rt.jar]
[Loaded java.lang.Comparable from /home/program/jdk1.8.0/jre/lib/rt.jar]
[Loaded java.lang.CharSequence from /home/program/jdk1.8.0/jre/lib/rt.jar]
[Loaded java.lang.String from /home/program/jdk1.8.0/jre/lib/rt.jar]
[Loaded java.lang.reflect.AnnotatedElement from /home/program/jdk1.8.0/jre/lib/rt.jar]
[Loaded java.lang.reflect.GenericDeclaration from /home/program/jdk1.8.0/jre/lib/rt.jar]
[Loaded java.lang.reflect.Type from /home/program/jdk1.8.0/jre/lib/rt.jar]
[Loaded java.lang.Class from /home/program/jdk1.8.0/jre/lib/rt.jar]
[Loaded java.lang.Cloneable from /home/program/jdk1.8.0/jre/lib/rt.jar]
......
[Loaded java.util.regex.Matcher from /home/program/jdk1.8.0/jre/lib/rt.jar]
[Loaded sun.misc.FloatingDecimal from /home/program/jdk1.8.0/jre/lib/rt.jar]
[Loaded sun.misc.FloatingDecimal$BinaryToASCIIConverter from /home/program/jdk1.8.0/jre/lib/rt.jar]
[Loaded sun.misc.FloatingDecimal$ExceptionalBinaryToASCIIBuffer from /home/program/jdk1.8.0/jre/lib/rt.jar]
[Loaded sun.misc.FloatingDecimal$BinaryToASCIIBuffer from /home/program/jdk1.8.0/jre/lib/rt.jar]
[Loaded sun.misc.FloatingDecimal$1 from /home/program/jdk1.8.0/jre/lib/rt.jar]
[Loaded sun.misc.FloatingDecimal$ASCIIToBinaryConverter from /home/program/jdk1.8.0/jre/lib/rt.jar]
[Loaded sun.misc.FloatingDecimal$PreparedASCIIToBinaryBuffer from /home/program/jdk1.8.0/jre/lib/rt.jar]
[Loaded sun.misc.FDBigInteger from /home/program/jdk1.8.0/jre/lib/rt.jar]
[Loaded java.lang.Shutdown from /home/program/jdk1.8.0/jre/lib/rt.jar]
[Loaded java.lang.Shutdown$Lock from /home/program/jdk1.8.0/jre/lib/rt.jar]
$ cat jvmload.txt | grep '^\[Loaded*' | awk '{print $2}'| sort
java.io.BufferedInputStream
java.io.BufferedOutputStream
java.io.BufferedReader
java.io.BufferedWriter
java.io.Closeable
java.io.DefaultFileSystem
java.io.ExpiringCache
java.io.ExpiringCache$1
java.io.ExpiringCache$Entry
java.io.File
......
sun.reflect.UnsafeFieldAccessorImpl
sun.reflect.UnsafeStaticFieldAccessorImpl
sun.security.action.GetPropertyAction
sun.security.util.Debug
sun.util.locale.BaseLocale
sun.util.locale.BaseLocale$Cache
sun.util.locale.BaseLocale$Key
sun.util.locale.LocaleObjectCache
sun.util.locale.LocaleObjectCache$CacheEntry
sun.util.locale.LocaleUtils
sun.util.PreHashedMap
$ cat jvmload.txt | grep '^\[Loaded*' | awk '{print $4}'| sort
file:/home/abc/project/jvm/Assignment1/bin/]
/home/program/jdk1.8.0/jre/lib/rt.jar]
/home/program/jdk1.8.0/jre/lib/rt.jar]
/home/program/jdk1.8.0/jre/lib/rt.jar]
/home/program/jdk1.8.0/jre/lib/rt.jar]
/home/program/jdk1.8.0/jre/lib/rt.jar]
/home/program/jdk1.8.0/jre/lib/rt.jar]
/home/program/jdk1.8.0/jre/lib/rt.jar]
/home/program/jdk1.8.0/jre/lib/rt.jar]
/home/program/jdk1.8.0/jre/lib/rt.jar]
......
/home/program/jdk1.8.0/jre/lib/rt.jar]
/home/program/jdk1.8.0/jre/lib/rt.jar]
/home/program/jdk1.8.0/jre/lib/rt.jar]
/home/program/jdk1.8.0/jre/lib/rt.jar]
/home/program/jdk1.8.0/jre/lib/rt.jar]
/home/program/jdk1.8.0/jre/lib/rt.jar]
/home/program/jdk1.8.0/jre/lib/rt.jar]
/home/program/jdk1.8.0/jre/lib/rt.jar]

通过这些输出,可以得知程序到底依赖哪些类和jar文件,在打包时只要将这些文件打包进去即可。

这里有一个gc输出,其最可能的JVM参数是什么?

1
2
3
4
5
6
7
8
9
10
11
Heap
def new generation total 6464K, used 115K [0x34e80000, 0x35580000, 0x35580000)
eden space 5760K, 2% used [0x34e80000, 0x34e9cd38, 0x35420000)
from space 704K, 0% used [0x354d0000, 0x354d0000, 0x35580000)
to space 704K, 0% used [0x35420000, 0x35420000, 0x354d0000)
tenured generation total 18124K, used 8277K [0x35580000, 0x36733000, 0x37680000)
the space 18124K, 45% used [0x35580000, 0x35d95758, 0x35d95800, 0x36733000)
compacting perm gen total 16384K, used 16383K [0x37680000, 0x38680000, 0x38680000)
the space 16384K, 99% used [0x37680000, 0x3867ffc0, 0x38680000, 0x38680000)
ro space 10240K, 44% used [0x38680000, 0x38af73f0, 0x38af7400, 0x39080000)
rw space 12288K, 52% used [0x39080000, 0x396cdd28, 0x396cde00, 0x39c80000)

由于输出信息包含永久代,因此可以确认这个jvm是java7或之前的版本。先计算新生代、老年代、永久代、以及新生代中的Eden区和Survival区的大小。

1
2
3
4
5
NewGen = (0x35580000-0x34e80000)/1024/1024 = 7M
TenGen = (0x37680000-0x35580000)/1024/1024 = 33M
PermGen = (0x38680000-0x37680000)/1024/1024 = 16M
Eden = (0x35420000-0x34e80000)/1024/1024 = 5.6M
Surv = (0x35580000-0x354d0000)/1024/1024 = 0.7M

所以,从内存分配上来看,NewRatio=33/7=4.7SurvivalRatio=5.6/0.7=8,NewRatio不应为小数,所以近似为5,可以确认的参数-XX:NewRatio=5 -XX:SurvivalRatio=8。不能确认的参数有最大堆大小-Xmx和最小堆大小-Xms,但当前堆大小=33+7=40M,因此,-Xmx的最小取值是40M。同样不确认的参数还有-XX:PermSize-XX:MaxPermSize,但-XX:MaxPermSize最小取值是16M。从打印信息的格式,可以推断,应该也用了-XX:+PrintGCDetails参数。

文章目录

欢迎来到Valleylord的博客!

本博的文章尽量原创。