一.关于性能的基本知识 
  1.性能的定义 
  在我们讨论怎样提高Java的性能之前,我们需要明白“性能“的真正含义。我们一般定义如下五个方面作为评判性能的标准。 
  1) 运算的性能----哪一个算法的执行性能最好 
  2) 内存的分配----程序需要分配多少内存,运行时的效率和性能最高。 
  3) 启动的时间----程序启动需要多少时间。 
  4) 程序的可伸缩性-----程序在用户负载过重的情况下的表现。 
  5) 性能的认识------用户怎样才能认识到程序的性能。 
  对于不同的应用程序,对性能的要求也不同。例如,大部分的应用程序在启动时需要较长的时间,从而对启动时间的要求有所降低;服务器端的应用程序通常都分配有较大的内存空间,所以对内存的要求也有所降低。但是,这并不是所这两方面的性能可以被忽略。其次,算法的性能对于那些把商务逻辑运用到事务性操作的应用程序来讲非常重要。总的来讲,对应用程序的要求将决定对各个性能的优先级。 
  2.怎样才能提高JAVA的性能 
  提高JAVA的性能,一般考虑如下的四个主要方面: 
  (1) 程序设计的方法和模式 
  一个良好的设计能提高程序的性能,这一点不仅适用于JAVA,也适用也任何的编程语言。因为它充分利用了各种资源,如内存,CPU,高速缓存,对象缓冲池及多线程,从而设计出高性能和可伸缩性强的系统。 
  当然,为了提高程序的性能而改变原来的设计是比较困难的,但是,程序性能的重要性常常要高于设计上带来的变化。因此,在编程开始之前就应该有一个好的设计模型和方法。 
  (2) JAVA布署的环境。 
  JAVA布署的环境就是指用来解释和执行JAVA字节码的技术,一般有如下五种。即解释指令技术(Interpreter Technology),及时编译的技术(Just In Time Compilier Technology), 适应性优化技术(Adaptive Optimization Technology), 动态优化,提前编译为机器码的技术(Dynamic Optimization,Ahead Of Time Technology)和编译为机器码的技术(Translator Technology). 
  这些技术一般都通过优化线程模型,调整堆和栈的大小来优化JAVA的性能。在考虑提高JAVA的性能时,首先要找到影响JAVA性能的瓶颈(BottleNecks),在确认了设计的合理性后,应该调整JAVA布署的环境,通过改变一些参数来提高JAVA应用程序的性能。具体内容见第二节。 
  (3) JAVA应用程序的实现 
  当讨论应用程序的性能问题时,大多数的程序员都会考虑程序的代码,这当然是对的,当更重要的是要找到影响程序性能的瓶颈代码。为了找到这些瓶颈代码,我们一般会使用一些辅助的工具,如Jprobe,Optimizit,Vtune以及一些分析的工具如TowerJ Performance等。这些辅助的工具能跟踪应用程序中执行每个函数或方法所消耗掉的时间,从而改善程序的性能。 
  (4) 硬件和操作系统 
  为了提高JAVA应用程序的性能,而采用跟快的CPU和更多的内存,并认为这是提高程序性能的唯一方法,但事实并非如此。实践经验和事实证明,只有遭到了应用程序性能的瓶颈,从而采取适当得方法,如设计模式,布署的环境,操作系统的调整,才是最有效的。 
  3.程序中通常的性能瓶颈。 
  所有的应用程序都存在性能瓶颈,为了提高应用程序的性能,就要尽可能的减少程序的瓶颈。以下是在JAVA程序中经常存在的性能瓶颈。 
了解了这些瓶颈后,就可以有针对性的减少这些瓶颈,从而提高JAVA应用程序的性能 
  4. 提高JAVA程序性能的步骤 
  为了提高JAVA程序的性能,需要遵循如下的六个步骤。 
  a) 明确对性能的具体要求 
  在实施一个项目之前,必须要明确该项目对于程序性能的具体要求,如:这个应用程序要支持5000个并发的用户,并且响应时间要在5秒钟之内。但同时也要明白对于性能的要求不应该同对程序的其他要求冲突。 
  b) 了解当前程序的性能 
  你应该了解你的应用程序的性能同项目所要求性能之间的差距。通常的指标是单位时间内的处理数和响应时间,有时还会比较CPU和内存的利用率。 
  c) 找到程序的性能瓶颈 
  为了发现程序中的性能瓶颈,通常会使用一些分析工具,如:TowerJ Application Performance Analyzer或VTune来察看和分析程序堆栈中各个元素的消耗时间,从而正确的找到并改正引起性能降低的瓶颈代码,从而提高程序的性能。这些工具还能发现诸如过多的异常处理,垃圾回收等潜在的问题。 
  d) 采取适当的措施来提高性能 
  找到了引起程序性能降低的瓶颈代码后,我们就可以用前面介绍过的提高性能的四个方面,即设计模式,JAVA代码的实现,布署JAVA的环境和操作系统来提高应用程序的性能。具体内容将在下面的内容中作详细说明。 
  e) 只进行某一方面的修改来提高性能 
  一次只改变可能引起性能降低的某一方面,然后观察程序的性能是否有所提高,而不应该一次改变多个方面,因为这样你将不知道到底哪个方面的改变提高了程序的性能,哪个方面没有,即不能知道程序瓶颈在哪。 
  f) 返回到步骤c,继续作类似的工作,一直达到要求的性能为止。

二. JAVA布署的环境和编译技术 
   开发JAVA应用程序时,首先把JAVA的源程序编译为与平台无关的字节码。这些字节码就可以被各种基于JVM的技术所执行。这些技术主要分为两个大类。即基于解释的技术和基于提前编译为本地码的技术。其示意图如下: 
具体可分为如下的五类:   
  a) 解释指令技术 
  其结构图和执行过程如下: 
JAVA的编译器首先把JAVA源文件编译为字节码。这些字节码对于JAVA虚拟机(JVM)来讲就是机器的指令码。然后,JAVA的解释器不断的循环取出字节码进行解释并执行。 
   这样做的优点是可以实现JAVA语言的跨平台,同时生成的字节码也比较紧凑。JAVA的一些优点,如安全性,动态性都得保持;但缺点是省生成的字节码没有经过什么优化,同全部编译好的本地码相比,速度比较慢。 
  b) 及时编译技术(Just In Time) 
    及时编译技术是为了解决指令解释技术效率比较低,速度比较慢的情况下提出的,其结构图如下所示。 
其主要变化是在JAVA程序执行之前,又JIT编译器把JAVA的字节码编译为机器码。从而在程序运行时直接执行机器码,而不用对字节码进行解释。同时对代码也进行了部分的优化。 
  这样做的优点是大大提高了JAVA程序的性能。同时,由于编译的结果并不在程序运行间保存,因此也节约了存储空间了加载程序的时间;缺点是由于JIT编译器对所有的代码都想优化,因此也浪费了很多的时间。 
  IBM和SUN公司都提供了相关的JIT产品。 
  c) 适应性优化技术(Adaptive Optimization Technology) 
  同JIT技术相比,适应性优化技术并不对所有的字节码进行优化。它会跟踪程序运行的成个过程,从而发现需要优化的代码,对代码进行动态的优化。对优化的代码,采取80/20的策略。从理论上讲,程序运行的时间越长,代码就越优化。其结构图如下: 
其优点是适应性优化技术充分利用了程序执行时的信息,发行程序的性能瓶颈,从而提高程序的性能;其缺点是在进行优化时可能会选择不当,发而降低了程序的性能。 
  其主要产品又IBM,SUN的HotSpot. 
  d) 动态优化,提前编译为机器码的技术(Dynamic Optimization,Ahead Of Time) 
  动态优化技术充分利用了JAVA源码编译,字节码编译,动态编译和静态编译的技术。其输入时JAVA的原码或字节码,而输出是经过高度优化的可执行代码和个来动态库的混合(Window中是DLL文件,UNIX中是共享库.a .so文件)。其结构如下: 
其优点是能大大提高程序的性能;缺点是破坏了JAVA的可移植性,也对JAVA的安全带来了一定的隐患。 
  其主要产品是TowerJ3.0. 
三.优化JAVA程序设计和编码,提高JAVA程序性能的一些方法。 
  通过使用一些前面介绍过的辅助性工具来找到程序中的瓶颈,然后就可以对瓶颈部分的代码进行优化。一般有两种方案:即优化代码或更改设计方法。我们一般会选择后者,因为不去调用以下代码要比调用一些优化的代码更能提高程序的性能。而一个设计良好的程序能够精简代码,从而提高性能。 
  下面将提供一些在JAVA程序的设计和编码中,为了能够提高JAVA程序的性能,而经常采用的一些方法和技巧。 
  1.对象的生成和大小的调整。 
  JAVA程序设计中一个普遍的问题就是没有好好的利用JAVA语言本身提供的函数,从而常常会生成大量的对象(或实例)。由于系统不仅要花时间生成对象,以后可能还需花时间对这些对象进行垃圾回收和处理。因此,生成过多的对象将会给程序的性能带来很大的影响。 
  例1:关于String ,StringBuffer,+和append 
  JAVA语言提供了对于String类型变量的操作。但如果使用不当,会给程序的性能带来影响。如下面的语句: 
  String name=new String(“HuangWeiFeng”); 
  System.out.println(name+”is my name”); 
  看似已经很精简了,其实并非如此。为了生成二进制的代码,要进行如下的步骤和操作。 
  (1) 生成新的字符串 new String(STR_1); 
  (2) 复制该字符串。 
  (3) 加载字符串常量”HuangWeiFeng”(STR_2); 
  (4) 调用字符串的构架器(Constructor); 
  (5) 保存该字符串到数组中(从位置0开始) 
  (6) 从java.io.PrintStream类中得到静态的out变量 
  (7) 生成新的字符串缓冲变量new StringBuffer(STR_BUF_1); 
  (8) 复制该字符串缓冲变量 
  (9) 调用字符串缓冲的构架器(Constructor); 
  (10) 保存该字符串缓冲到数组中(从位置1开始) 
  (11) 以STR_1为参数,调用字符串缓冲(StringBuffer)类中的append方法。 
  (12) 加载字符串常量”is my name”(STR_3); 
  (13) 以STR_3为参数,调用字符串缓冲(StringBuffer)类中的append方法。 
  (14) 对于STR_BUF_1执行toString命令。 
  (15) 调用out变量中的println方法,输出结果。 
  由此可以看出,这两行简单的代码,就生成了STR_1,STR_2,STR_3,STR_4和STR_BUF_1五个对象变量。这些生成的类的实例一般都存放在堆中。堆要对所有类的超类,类的实例进行初始化,同时还要调用类极其每个超类的构架器。而这些操作都是非常消耗系统资源的。因此,对对象的生成进行限制,是完全有必要的。 
  经修改,上面的代码可以用如下的代码来替换。 
  StringBuffer name=new StringBuffer(“HuangWeiFeng”); 
  System.out.println(name.append(“is my name.”).toString()); 
  系统将进行如下的操作。 
  (1) 生成新的字符串缓冲变量new StringBuffer(STR_BUF_1); 
  (2) 复制该字符串缓冲变量 
  (3) 加载字符串常量”HuangWeiFeng”(STR_1); 
  (4) 调用字符串缓冲的构架器(Constructor); 
  (5) 保存该字符串缓冲到数组中(从位置1开始) 
  (6) 从java.io.PrintStream类中得到静态的out变量 
  (7) 加载STR_BUF_1; 
  (8) 加载字符串常量”is my name”(STR_2); 
  (9) 以STR_2为参数,调用字符串缓冲(StringBuffer)实例中的append方法。 
  (10) 对于STR_BUF_1执行toString命令。(STR_3) 
  (11)调用out变量中的println方法,输出结果。 
  由此可以看出,经过改进后的代码只生成了四个对象变量:STR_1,STR_2,STR_3和STR_BUF_1.你可能觉得少生成一个对象不会对程序的性能有很大的提高。但下面的代码段2的执行速度将是代码段1的2倍。因为代码段1生成了八个对象,而代码段2只生成了四个对象。 
  代码段1: 
  String name= new StringBuffer(“HuangWeiFeng”); 
  name+=”is my”; 
  name+=”name”; 
  代码段2: 
  StringBuffer name=new StringBuffer(“HuangWeiFeng”); 
  name.append(“is my”); 
  name.append(“name.”).toString(); 
  因此,充分的利用JAVA提供的库函数来优化程序,对提高JAVA程序的性能时非常重要的.其注意点主要有如下几方面; 
  (1) 尽可能的使用静态变量(Static Class Variables) 
  如果类中的变量不会随他的实例而变化,就可以定义为静态变量,从而使他所有的实例都共享这个变量。 
  例: 
  public class foo 
  { 
  SomeObject so=new SomeObject(); 
  } 
  就可以定义为: 
  public class foo 
  { 
  static SomeObject so=new SomeObject(); 
  } 
  (2) 不要对已生成的对象作过多的改变。 
  对于一些类(如:String类)来讲,宁愿在重新生成一个新的对象实例,而不应该修改已经生成的对象实例。 
  例: 
  String name=”Huang”; 
  name=”Wei”; 
  name=”Feng”; 
  上述代码生成了三个String类型的对象实例。而前两个马上就需要系统进行垃圾回收处理。如果要对字符串进行连接的操作,性能将得更差。因为系统将不得为此生成更多得临时变量。如上例1所示。 
  (3) 生成对象时,要分配给它合理的空间和大小 
  JAVA中的很多类都有它的默认的空间分配大小。对于StringBuffer类来讲,默认的分配空间大小是16个字符。如果在程序中使用StringBuffer的空间大小不是16个字符,那么就必须进行正确的初始化。 
  (4) 避免生成不太使用或生命周期短的对象或变量。 
  对于这种情况,因该定义一个对象缓冲池。以为管理一个对象缓冲池的开销要比频繁的生成和回收对象的开销小的多。 
  (5) 只在对象作用范围内进行初始化。 
  JAVA允许在代码的任何地方定义和初始化对象。这样,就可以只在对象作用的范围内进行初始化。从而节约系统的开销。 
  例: 
  SomeObject so=new SomeObject(); 
  If(x==1) then 
  { 
  Foo=so.getXX(); 
  } 
  可以修改为: 
  if(x==1) then 
  { 
  SomeObject so=new SomeObject(); 
  Foo=so.getXX(); 
  } 
  2.异常(Exceptions) 
  JAVA语言中提供了try/catch来发方便用户捕捉异常,进行异常的处理。但是如果使用不当,也会给JAVA程序的性能带来影响。因此,要注意以下两点。 
  (1) 避免对应用程序的逻辑使用try/catch 
  如果可以用if,while等逻辑语句来处理,那么就尽可能的不用try/catch语句 
  (2) 重用异常 
  在必须要进行异常的处理时,要尽可能的重用已经存在的异常对象。以为在异常的处理中,生成一个异常对象要消耗掉大部分的时间。 
  3. 线程(Threading) 
  一个高性能的应用程序中一般都会用到线程。因为线程能充分利用系统的资源。在其他线程因为等待硬盘或网络读写而 时,程序能继续处理和运行。但是对线程运用不当,也会影响程序的性能。 
例2:正确使用Vector类 
  Vector主要用来保存各种类型的对象(包括相同类型和不同类型的对象)。但是在一些情况下使用会给程序带来性能上的影响。这主要是由Vector类的两个特点所决定的。第一,Vector提供了线程的安全保护功能。即使Vector类中的许多方法同步。但是如果你已经确认你的应用程序是单线程,这些方法的同步就完全不必要了。第二,在Vector查找存储的各种对象时,常常要花很多的时间进行类型的匹配。而当这些对象都是同一类型时,这些匹配就完全不必要了。因此,有必要设计一个单线程的,保存特定类型对象的类或集合来替代Vector类.用来替换的程序如下(StringVector.java): 
  public class StringVector 
  { 
  private String [] data; 
  private int count; 
  public StringVector() { this(10); // default size is 10 } 
  public StringVector(int initialSize) 
  { 
  data = new String[initialSize]; 
  } 
  public void add(String str) 
  { 
  // ignore null strings 
  if(str == null) { return; } 
  ensureCapacity(count + 1); 
  data[count++] = str; 
  } 
   
  private void ensureCapacity(int minCapacity) 
  { 
  int oldCapacity = data.length; 
  if (minCapacity > oldCapacity) 
  { 
  String oldData[] = data; 
  int newCapacity = oldCapacity * 2; 
  data = new String[newCapacity]; 
  System.arraycopy(oldData, 0, data, 0, count); 
  } 
  } 
  public void remove(String str) 
  { 
  if(str == null) { return // ignore null str } 
  for(int i = 0; i  count) 
  { 
  return null; // index is > # strings 
  } 
  else { return data[index]; // index is good } 
  } 
  /* * * * * * * * * * * * * * * *StringVector.java * * * * * * * * * * * * * * * * */ 
  因此,代码: 
  Vector Strings=new Vector(); 
  Strings.add(“One”); 
  Strings.add(“Two”); 
  String Second=(String)Strings.elementAt(1); 
  可以用如下的代码替换: 
  StringVector Strings=new StringVector(); 
  Strings.add(“One”); 
  Strings.add(“Two”); 
  String Second=Strings.getStringAt(1); 
  这样就可以通过优化线程来提高JAVA程序的性能。用于测试的程序如下(TestCollection.java): 
  import java.util.Vector; 
  public class TestCollection 
  { 
  public static void main(String args []) 
  { 
  TestCollection collect = new TestCollection(); 
  if(args.length == 0) 
  { 
  System.out.println( 
  "Usage: java TestCollection [ vector   stringvector ]"); 
  System.exit(1); 
  } 
  if(args[0].equals("vector")) 
  { 
  Vector store = new Vector(); 
  long start = System.currentTimeMillis(); 
  for(int i = 0; i

java性能的更多相关文章

  1. Java 性能分析工具 , 第 3 部分: Java Mission Control

    引言 本文为 Java 性能分析工具系列文章第三篇,这里将介绍如何使用 Java 任务控制器 Java Mission Control 深入分析 Java 应用程序的性能,为程序开发人员在使用 Jav ...

  2. Java 性能分析工具 , 第 2 部分:Java 内置监控工具

    引言 本文为 Java 性能分析工具系列文章第二篇,第一篇:操作系统工具.在本文中将介绍如何使用 Java 内置监控工具更加深入的了解 Java 应用程序和 JVM 本身.在 JDK 中有许多内置的工 ...

  3. Java 性能优化之 String 篇

    原文:http://www.ibm.com/developerworks/cn/java/j-lo-optmizestring/ Java 性能优化之 String 篇 String 方法用于文本分析 ...

  4. 【转发】关于Java性能的9个谬论

    转载请注明出处,感谢大家的支持!本文来自优优码:http://www.uucode.net/201502/9%e4%b8%aa%e8%b0%ac%e8%ae%ba Java的性能有某种黑魔法之称.部分 ...

  5. java 性能优化(代码优化)

    参考博文: java 性能优化:35 个小细节,让你提升 java 代码的运行效率

  6. 读书笔记系列之java性能优化权威指南 一 第一章

    主题:java性能优化权威指南 pdf 版本:英文版 Java Performance Tuning 忽略:(0~24页)Performance+Acknowledge 1.Strategies, A ...

  7. 浅谈java性能分析

    浅谈java性能分析,效能分析 在老师强烈的要求下做了效能分析,对上次写过的词频统计的程序进行分析以及改进. 对于效能分析:我个人很浅显的认为就是程序的运行效率,代码的执行效率等等. java做性能测 ...

  8. [原创]Java性能优化权威指南读书思维导图

    [原创]Java性能优化权威指南读书思维导图 书名:Java性能优化权威指南 原书名:Java performance 作者: (美)Charlie Hunt    Binu John 译者: 柳飞 ...

  9. Java性能调优笔记

    Java性能调优笔记 调优步骤:衡量系统现状.设定调优目标.寻找性能瓶颈.性能调优.衡量是否到达目标(如果未到达目标,需重新寻找性能瓶颈).性能调优结束. 寻找性能瓶颈 性能瓶颈的表象:资源消耗过多. ...

  10. 最大化 AIX 上的 Java 性能,第 5 部分: 参考资料和结论

    http://www.ibm.com/developerworks/cn/aix/library/es-Javaperf/es-Javaperf5.html 最大化 AIX 上的 Java 性能,第 ...

随机推荐

  1. nyoj 203 三国志(最短路加01背包)

    三国志 时间限制:3000 ms  |  内存限制:65535 KB 难度:5   描述 <三国志>是一款很经典的经营策略类游戏.我们的小白同学是这款游戏的忠实玩家.现在他把游戏简化一下, ...

  2. Educational Codeforces Round 7 - E. Ants in Leaves

    题目链接:http://www.codeforces.com/contest/622/problem/E 题意是给你一棵树,1为根,每个叶子节点有一个蚂蚁,移动到一个邻接节点时间耗费为1,一个节点上不 ...

  3. ActiveMQ学习笔记(二) JMS与Spring

    上文可见,JMS Native API使用起来不是特别方便.好在Spring提供了很好的JMS支持. (一)配置ConnectionFactory 如果使用连接池的话,不要忘记activemq-poo ...

  4. Android改变了PDA市场格局

    看到一则消息<联想PDA助力306医院智慧医疗建设>,看完后感慨颇多:"大象"终于开始踩"蚂蚁"了!虽然主观上感觉这种做法很不地道,同时为传统PDA ...

  5. zendstudio 10下载汉化

      1.文件和汉化文件 ZendStudio官方下载地址:http://www.geekso.com/component/zendstudio-downloads/ 百度云地址: 10.0.0.msi ...

  6. sre_constants.error: unbalanced parenthesis

    Traceback (most recent call last):   File "androidmarket82.py", line 108, in <module> ...

  7. LINQ to XML 从逗号分隔值 (CSV) 文件生成 XML 文件

    参考:http://msdn.microsoft.com/zh-cn/library/bb387090.aspx 本示例演示如何使用 语言集成查询 (LINQ) 和 LINQ to XML 从逗号分隔 ...

  8. Web项目的三层架构和MVC架构异同

    http://www.cnblogs.com/zhhh/archive/2011/06/10/2077519.html 又看到有人在问三层架构和MVC的关系,感觉这种问题有点教条化了.因为它们都在逻辑 ...

  9. 浅谈IT员工管理

    本人尽管还不是管理人员,但也管理过学弟们(不是同校.仅仅是工作中同事,为了好称呼叫学弟).也被管理着,工作也好多年了.今天又感而发.想来谈谈假设管理好员工(在此声明,我仅仅是发表个人意见哦.不要喷.哈 ...

  10. 发布站点到远程FTP根目录

    第一步:修改 phpcms/modules/admin/templates/site_add.tpl.php 找到 <legend><?php echo L('release_poi ...