新的JavaTM 虚拟机(VMs)具有能够提高性能的特点, 并且你可以使用许多工具来提高应用程序的性能或减小一般类文件的尺寸。这种Java虚拟机的特性和工具可使你在不改变应用程序、或对应用程序仅做很小改动的情况下, 提高应用程序的性能。
Java虚拟机的特性
Java2与过去的版本相比, 性能已有很大提高, 其中包括更快的内存分配、类尺寸的减小、垃圾收集的改善、最新型的监控器和作为标准的内联JIT技术。当使用新的Java2虚拟机时, 你会看到这种性能的改善; 然而, 假如你能够理解速度是如何提高的, 你就能够调整你的应用程序, 以充分挖掘每一点性能潜力。
方法内联
Java虚拟机的Java2版可在运行时自动内联简单方法。在一个未优化的Java虚拟机中,每调用一次新的方法,就创建一个新的堆栈帧(stack frame)。创建一个新的堆栈帧需要一些额外的资源以及该栈的某些再映射(re-mapping),其结果将导致系统开销的少许增加。
由于方法内联可在你的程序中减少方法调用的次数,因而可提高性能。Java虚拟机内联代码内联了返回常数或仅访问内部域(internal fields)的方法。为了利用方法内联,你可以从以下两件事中选做其一;即:你可以使一个方法对虚拟机所要执行的内联看上去是有吸引力的,或者你可以手工内联一个方法,只要它不破坏你的对象模型。在这一语境中的手工内联意味着可以直接从一个方法中将代码移动到正在调用该方法的方法中。
下面的小例子演示了虚拟机的自动方法内联:
public class InlineMe {
int counter=0;
public void method1() {
for(int i=0;i<1000;i++)
addCount();
System.out.println("counter="+counter);
}
public int addCount() {
counter=counter+1;
return counter;
}
public static void main(String args[]) {
InlineMe im=new InlineMe();
im.method1();
}
}
在当前状态,addCount方法对虚拟机中的内联探测器显得是没有吸引力的,因为addCount方法返回一个值。要发现该方法是否被内联:
java -Xrunhprof:cpu=times InlineMe
它生成一个java.hprof.txt输出文件。前十个方法类似下面的结果:
CPU TIME (ms) BEGIN (total = 510) Thu Jan 28 16:56:15 1999
rank self accum count trace method
1 5.88% 5.88% 1 25 java/lang/Character.
2 3.92% 9.80% 5808 13 java/lang/String.charAt
3 3.92% 13.73% 1 33 sun/misc/Launcher$AppClassLoader.getPermissions
4 3.92% 17.65% 3 31 sun/misc/URLClassPath.getLoader
5 1.96% 19.61% 1 39 java/net/URLClassLoader.Access$1
6 1.96% 21.57% 1000 46 InlineMe.addCount
7 1.96% 23.53% 1 21 sun/io/Converters.newConverter
8 1.96% 25.49% 1 17 sun/misc/Launcher$ExtClassLoader.getExtDirs
9 1.96% 27.45% 1 49 java/util/Stack.peek
10 1.96% 29.41% 1 24 sun/misc/Launcher.
假如你将addCount方法改变为不再返回一个值,则虚拟机可在运行时将其内联。为使内联代码更友好,应用下面的程序替换addCount方法:
public void addCount() {
counter=counter+1;
}
再次运行profiler:
java -Xrunhprof:cpu=times InlineMe
这次,java.hprof.txt的输出应该显得是不同的。
AddCount方法已经消失。它已被内联了!
CPU TIME (ms) BEGIN (total = 560) Thu Jan 28 16:57:02 1999
rank self accum count trace method
1 5.36% 5.36% 1 27 java/lang/Character.
2 3.57% 8.93% 1 23 java/lang/System.initializeSystemClass
3 3.57% 12.50% 2 47 java/io/PrintStream.
4 3.57% 16.07% 5808 15 java/lang/String.charAt
5 3.57% 19.64% 1 42 sun/net/www/protocol/file/Handler.openConnection
6 1.79% 21.43% 2 21 java/io/InputStreamReader.fill
7 1.79% 23.21% 1 54 java/lang/Thread.
8 1.79% 25.00% 1 39 java/io/PrintStream.write
9 1.79% 26.79% 1 40 java/util/jar/JarFile.getJarEntry
10 1.79% 28.57% 1 38 java/lang/Class.forName0