java Exception 性能问题
依稀还记得,try{}之后的代码块应尽量越少越好,难道代码被try{}catch(){}包围之后会降低运行效率吗?
测试一下:
package exception;public class TestTry_Catch{public static boolean try_catch(){try{return true;} catch (Exception e){return false;}}public static boolean no_try_catch(){return true;}public static void main(String[] args){long current1 = System.currentTimeMillis();long time = 10000000000l;for (long i = 0l; i < time; i++)try_catch();long current2 = System.currentTimeMillis();for (long j = 0l; j < time; j++)no_try_catch();long current3 = System.currentTimeMillis();System.out.println("try_catch time : " + (current2 - current1) + " ms");System.out.println("no_try_catch time : " + (current3 - current2) + " ms");}}?下面是console输出:
try_catch time : 4843 msno_try_catch time : 4683 ms
?这么多次,相差依然很小,在不会发生异常的情况下try_catch方法和no_try_catch方法运行的时间基本相差无几,在即时编译时try_catch方法比no_try_catch方法应花费稍多时间
?
下面再看一个更有趣的,当把return type改为void 时,代码:
package exception;public class TestTry_Catch{public static void try_catch(){try{// return true;} catch (Exception e){// return false;}}public static void no_try_catch(){// return true;}public static void main(String[] args){long current1 = System.currentTimeMillis();long time = 10000000000l;for (long i = 0l; i < time; i++)try_catch();long current2 = System.currentTimeMillis();for (long j = 0l; j < time; j++)no_try_catch();long current3 = System.currentTimeMillis();System.out.println("try_catch time : " + (current2 - current1) + " ms");System.out.println("no_try_catch time : " + (current3 - current2) + " ms");}}?console 输出:
try_catch time : 4772 msno_try_catch time : 4918 ms
?try_catch 比no_try_catch花费的时间更少了,这该怎样解释呢?
?
让方法进行一些计算吧,不去创建对象,因为可能会触发GC,只是去计算一下1+1
package exception;public class TestTry_Catch{public static void try_catch(){try{int a = 1 + 1;int b = a + 3;} catch (Exception e){// return false;}}public static void no_try_catch(){int a = 1 + 1;int b = a + 3;}public static void main(String[] args){long current1 = System.currentTimeMillis();long time = 10000000000l;for (long i = 0l; i < time; i++)try_catch();long current2 = System.currentTimeMillis();for (long j = 0l; j < time; j++)no_try_catch();long current3 = System.currentTimeMillis();System.out.println("try_catch time : " + (current2 - current1) + " ms");System.out.println("no_try_catch time : " + (current3 - current2) + " ms");}}?console输出:
try_catch time : 4957 msno_try_catch time : 4934 ms
?
我开始怀疑 try{}catch(){}代码块越短越好 这句话的正确性了
?
下面测一下异常对象产的的耗时和普通对象产生的耗时比较:
?
package exception;import exception.entity.My_Exception;public class New_Object_Exception{public static void main(String[] args){for (int i = 0; i < 10000; i++)new Throwable();long number = 100000l;long current1 = System.currentTimeMillis();for (long j = 0l; j < number; j++)new My_Exception();long current2 = System.currentTimeMillis();for (long i = 0l; i < number; i++)new Exception();long current3 = System.currentTimeMillis();System.out.println("new My_Exception time : " + (current2 - current1) + " ms");System.out.println("new Exception time : " + (current3 - current2) + " ms");}}?console输出:
new My_Exception time : 113 msnew Exception time : 144 ms
?相差很小,一个数量级,无视GC了
?
下面测一下抛出异常到接收到异常的时间,代码如下:
?
package exception;import exception.entity.My_Exception;public class Catch_Exception{public static void main(String[] args){long time = 100000l;for (int i = 0; i < 10000; i++){new Throwable();}long current1 = System.currentTimeMillis();for (long i = 0l; i < time; i++){try{throw new Exception();} catch (Exception e){}}long current2 = System.currentTimeMillis();for (long i = 0l; i < time; i++){try{throw new My_Exception();} catch (My_Exception e){}}long current3 = System.currentTimeMillis();System.out.println("catch Exception : " + (current2 - current1) + " ms");System.out.println("catch My_Exception : " + (current3 - current2) + " ms");}}?console输出:
?
catch Exception : 77 mscatch My_Exception : 64 ms
?
?
贴一下jdk中Throwable 类的getMessage(), getStackTrace()源码
?
getMessage():
public String getMessage() { return detailMessage; }?detailMessage只是Throwable类的一个私有变量
private String detailMessage;
?
getStackTrace():
public StackTraceElement[] getStackTrace() { return getOurStackTrace().clone(); }?getOurStackTrace():
private synchronized StackTraceElement[] getOurStackTrace() { // Initialize stack trace field with information from // backtrace if this is the first call to this method if (stackTrace == UNASSIGNED_STACK || (stackTrace == null && backtrace != null) /* Out of protocol state */) { int depth = getStackTraceDepth(); stackTrace = new StackTraceElement[depth]; for (int i=0; i < depth; i++) stackTrace[i] = getStackTraceElement(i); } else if (stackTrace == null) { return UNASSIGNED_STACK; } return stackTrace; }?如果不是自定义的异常对象,大概没必要去调这个方法,如果不调这个方法抛出异常,捕获异常,貌似对性能也没什么影响
?
关于异常,各有各的想法吧
?
另外我的电脑配置:i5 win7 64位 4G内存, jdk : jdk1.7.0_10 b18 64位