﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>语源科技BlogJava-LetsCoding.cn</title><link>http://www.blogjava.net/4cai/</link><description>天地之间有杆秤，拿秤砣砸老百姓。</description><language>zh-cn</language><lastBuildDate>Tue, 12 May 2026 08:55:27 GMT</lastBuildDate><pubDate>Tue, 12 May 2026 08:55:27 GMT</pubDate><ttl>60</ttl><item><title>JVM中finally子句介绍</title><link>http://www.blogjava.net/4cai/archive/2014/06/08/414503.html</link><dc:creator>Rolandz</dc:creator><author>Rolandz</author><pubDate>Sat, 07 Jun 2014 18:42:00 GMT</pubDate><guid>http://www.blogjava.net/4cai/archive/2014/06/08/414503.html</guid><wfw:comment>http://www.blogjava.net/4cai/comments/414503.html</wfw:comment><comments>http://www.blogjava.net/4cai/archive/2014/06/08/414503.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/4cai/comments/commentRss/414503.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/4cai/services/trackbacks/414503.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 欢迎来到“Under The Hood”第七期。本期我们介绍JVM处理finally子句的方式及相关字节码。你可能需要阅读往期的文章才能更好的理解本文。<br><br>finally子句<br><br>JVM执行Java字节码时，它有几种方式可以退出一个代码块（花括号中间的语句）。其中之一，就是简单的执行完其中所有的语句，然后退出代码块。第二种，JVM可能会在代码块中间的任何一处，遇到像break，continue，return之类的语句，强制它跳出该代码块。第三种，JVM可能会在执行过程中，出现了异常，然后它跳转到匹配的catch子句，或者没有找到相应的catch子句，直接退出当前线程。由于单个代码块有如此多的潜在退出点（exit point），拥有一个简单的方式来表达“无论代码块以什么方式退出，有些事情总能发生”是很值得的。然后就有了try-finally子句。&nbsp;&nbsp;<a href='http://www.blogjava.net/4cai/archive/2014/06/08/414503.html'>阅读全文</a><img src ="http://www.blogjava.net/4cai/aggbug/414503.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/4cai/" target="_blank">Rolandz</a> 2014-06-08 02:42 <a href="http://www.blogjava.net/4cai/archive/2014/06/08/414503.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JVM中的异常处理</title><link>http://www.blogjava.net/4cai/archive/2014/06/02/414314.html</link><dc:creator>Rolandz</dc:creator><author>Rolandz</author><pubDate>Sun, 01 Jun 2014 19:54:00 GMT</pubDate><guid>http://www.blogjava.net/4cai/archive/2014/06/02/414314.html</guid><wfw:comment>http://www.blogjava.net/4cai/comments/414314.html</wfw:comment><comments>http://www.blogjava.net/4cai/archive/2014/06/02/414314.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/4cai/comments/commentRss/414314.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/4cai/services/trackbacks/414314.html</trackback:ping><description><![CDATA[<p style="margin: 1rem 0px; padding: 0px; border: 0px; vertical-align: baseline; line-height: 24px; color: #444444; font-family: 'Open Sans', Helvetica, Arial, sans-serif;"><em style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">欢迎来到&#8220;<a href="http://letscoding.cn/tag/under-the-hood/" title="under the hood" target="_blank" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; outline: none; color: #21759b;">Under The Hood</a>&#8221;第六期。本期我们介绍<a href="http://letscoding.cn/jvm%E4%B8%AD%E7%9A%84%E5%BC%82%E5%B8%B8%E5%A4%84%E7%90%86/" title="jvm中的异常处理" target="_blank" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; outline: none; color: #21759b;">JVM处理异常的方式</a>，包括如何抛出和捕获异常及相关的字节码指令。但本文不会讨论finally子句，这是下期的主题。你可能需要阅读<a href="http://letscoding.cn/tag/under-the-hood/" title="under the hood" target="_blank" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; outline: none; color: #21759b;">往期</a>的文章才能更好的理解本文。</em></p>
<p style="margin: 1rem 0px; padding: 0px; border: 0px; vertical-align: baseline; line-height: 24px; color: #444444; font-family: 'Open Sans', Helvetica, Arial, sans-serif;"><em style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;"><strong style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">异常处理</strong></em></p>
<p style="margin: 1rem 0px; padding: 0px; border: 0px; vertical-align: baseline; line-height: 24px; color: #444444; font-family: 'Open Sans', Helvetica, Arial, sans-serif;">在程序运行时，异常让你可以平滑的处理意外状况。为了演示JVM处理异常的方式，考虑NitPickyMath类，它提供对整数进行加，减，乘，除以及取余的操作。<br />
</p>
<p style="margin: 1rem 0px; padding: 0px; border: 0px; vertical-align: baseline; line-height: 24px; color: #444444; font-family: 'Open Sans', Helvetica, Arial, sans-serif;">NitPickyMath提供的这些操作和Java语言的&#8220;+&#8221;，&#8220;-&#8221;，&#8220;*&#8221;，&#8220;/&#8221;和&#8220;%&#8221;是一样的，除了NitPickyMath中的方法在以下情况下会抛出检查型（checked）异常：上溢出，下溢出以及被0除。0做除数时，JVM会抛出ArithmeticException异常，但是上溢出和下溢出不会引发任何异常。NitPickyMath中抛出异常的方法定义如下：</p>
<div no="" java"="" style="margin: 0px 0px 1em; font-size: 11px; vertical-align: baseline; overflow: auto; white-space: nowrap; position: relative; font-family: monospace; color: #444444; background: #f3f3f3;">
<ol style="margin: 0px; padding: 0px 0px 0px 0em; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-style: none; vertical-align: baseline; list-style: none outside; line-height: 1.714285714;">
     <li style="margin: 0px 0px 0px 2.571428571rem; padding: 0px; border: 0px; vertical-align: baseline; list-style-type: none;">
     <div style="margin: 0px; padding-left: 5px; border: 0px; vertical-align: baseline; color: #000000; background: none;"><span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; font-weight: bold;">class</span>&nbsp;OverflowException&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; font-weight: bold;">extends</span>&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #0000cc;">Exception</span>&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #66cc66;">{</span></div>
     </li>
     <li style="margin: 0px 0px 0px 2.571428571rem; padding: 0px; border: 0px; vertical-align: baseline; list-style-type: none;">
     <div style="margin: 0px; padding-left: 5px; border: 0px; vertical-align: baseline; color: #000000; background: none;"><span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #66cc66;">}</span></div>
     </li>
     <li style="margin: 0px 0px 0px 2.571428571rem; padding: 0px; border: 0px; vertical-align: baseline; list-style-type: none;">
     <div style="margin: 0px; padding-left: 5px; border: 0px; vertical-align: baseline; color: #000000; background: none;"><span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; font-weight: bold;">class</span>&nbsp;UnderflowException&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; font-weight: bold;">extends</span>&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #0000cc;">Exception</span>&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #66cc66;">{</span></div>
     </li>
     <li style="margin: 0px 0px 0px 2.571428571rem; padding: 0px; border: 0px; vertical-align: baseline; list-style-type: none;">
     <div style="margin: 0px; padding-left: 5px; border: 0px; vertical-align: baseline; color: #000000; background: none;"><span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #66cc66;">}</span></div>
     </li>
     <li style="margin: 0px 0px 0px 2.571428571rem; padding: 0px; border: 0px; vertical-align: baseline; list-style-type: none;">
     <div style="margin: 0px; padding-left: 5px; border: 0px; vertical-align: baseline; color: #000000; background: none;"><span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; font-weight: bold;">class</span>&nbsp;DivideByZeroException&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; font-weight: bold;">extends</span>&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #0000cc;">Exception</span>&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #66cc66;">{</span></div>
     </li>
     <li style="margin: 0px 0px 0px 2.571428571rem; padding: 0px; border: 0px; vertical-align: baseline; list-style-type: none;">
     <div style="margin: 0px; padding-left: 5px; border: 0px; vertical-align: baseline; color: #000000; background: none;"><span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #66cc66;">}</span></div>
     </li>
</ol>
</div>
<p style="margin: 1rem 0px; padding: 0px; border: 0px; vertical-align: baseline; line-height: 24px; color: #444444; font-family: 'Open Sans', Helvetica, Arial, sans-serif;">NitPickyMath类中的remainder()方法就是一个抛出和捕获异常的简单方法。</p>
<div no="" java"="" style="margin: 0px 0px 1em; font-size: 11px; vertical-align: baseline; overflow: auto; white-space: nowrap; position: relative; font-family: monospace; color: #444444; background: #f3f3f3;">
<ol style="margin: 0px; padding: 0px 0px 0px 0em; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-style: none; vertical-align: baseline; list-style: none outside; line-height: 1.714285714;">
     <li style="margin: 0px 0px 0px 2.571428571rem; padding: 0px; border: 0px; vertical-align: baseline; list-style-type: none;">
     <div style="margin: 0px; padding-left: 5px; border: 0px; vertical-align: baseline; color: #000000; background: none;"><span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; font-weight: bold;">static</span>&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #f63333;">int</span>&nbsp;remainder<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #66cc66;">(</span><span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #f63333;">int</span>&nbsp;dividend,&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #f63333;">int</span>&nbsp;divisor<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #66cc66;">)</span></div>
     </li>
     <li style="margin: 0px 0px 0px 2.571428571rem; padding: 0px; border: 0px; vertical-align: baseline; list-style-type: none;">
     <div style="margin: 0px; padding-left: 5px; border: 0px; vertical-align: baseline; color: #000000; background: none;">&nbsp; &nbsp;&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; font-weight: bold;">throws</span>&nbsp;DivideByZeroException&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #66cc66;">{</span></div>
     </li>
     <li style="margin: 0px 0px 0px 2.571428571rem; padding: 0px; border: 0px; vertical-align: baseline; list-style-type: none;">
     <div style="margin: 0px; padding-left: 5px; border: 0px; vertical-align: baseline; color: #000000; background: none;">&nbsp; &nbsp;&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; font-weight: bold;">try</span>&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #66cc66;">{</span></div>
     </li>
     <li style="margin: 0px 0px 0px 2.571428571rem; padding: 0px; border: 0px; vertical-align: baseline; list-style-type: none;">
     <div style="margin: 0px; padding-left: 5px; border: 0px; vertical-align: baseline; color: #000000; background: none;">&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; font-weight: bold;">return</span>&nbsp;dividend&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">%</span>&nbsp;divisor<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">;</span></div>
     </li>
     <li style="margin: 0px 0px 0px 2.571428571rem; padding: 0px; border: 0px; vertical-align: baseline; list-style-type: none;">
     <div style="margin: 0px; padding-left: 5px; border: 0px; vertical-align: baseline; color: #000000; background: none;">&nbsp; &nbsp;&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #66cc66;">}</span></div>
     </li>
     <li style="margin: 0px 0px 0px 2.571428571rem; padding: 0px; border: 0px; vertical-align: baseline; list-style-type: none;">
     <div style="margin: 0px; padding-left: 5px; border: 0px; vertical-align: baseline; color: #000000; background: none;">&nbsp; &nbsp;&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; font-weight: bold;">catch</span>&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #66cc66;">(</span><span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #0000cc;">ArithmeticException</span>&nbsp;e<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #66cc66;">)</span>&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #66cc66;">{</span></div>
     </li>
     <li style="margin: 0px 0px 0px 2.571428571rem; padding: 0px; border: 0px; vertical-align: baseline; list-style-type: none;">
     <div style="margin: 0px; padding-left: 5px; border: 0px; vertical-align: baseline; color: #000000; background: none;">&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; font-weight: bold;">throw</span>&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; font-weight: bold;">new</span>&nbsp;DivideByZeroException<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #66cc66;">(</span><span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #66cc66;">)</span><span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">;</span></div>
     </li>
     <li style="margin: 0px 0px 0px 2.571428571rem; padding: 0px; border: 0px; vertical-align: baseline; list-style-type: none;">
     <div style="margin: 0px; padding-left: 5px; border: 0px; vertical-align: baseline; color: #000000; background: none;">&nbsp; &nbsp;&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #66cc66;">}</span></div>
     </li>
     <li style="margin: 0px 0px 0px 2.571428571rem; padding: 0px; border: 0px; vertical-align: baseline; list-style-type: none;">
     <div style="margin: 0px; padding-left: 5px; border: 0px; vertical-align: baseline; color: #000000; background: none;"><span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #66cc66;">}</span></div>
     </li>
</ol>
</div>
<p style="margin: 1rem 0px; padding: 0px; border: 0px; vertical-align: baseline; line-height: 24px; color: #444444; font-family: 'Open Sans', Helvetica, Arial, sans-serif;">remainder()方法，只是简单的对当作参数传递进来的2个整数进行取余操作。如果取余操作的除数是0，会引发ArithmeticException异常。remainder()方法捕获这个异常，并重新抛出DivideByZeroException异常。</p>
<p style="margin: 1rem 0px; padding: 0px; border: 0px; vertical-align: baseline; line-height: 24px; color: #444444; font-family: 'Open Sans', Helvetica, Arial, sans-serif;">DivideByZeroException和ArithmeticException的区别是，DivideByZeroException是检查型（checked）异常，而ArithmeticException是非检查（unchecked）型异常。由于ArithmeticException是非检查型异常，一个方法就算会抛出该异常，也不必在其throw子句中声明它。任何Error或RuntimeException异常的子类异常都是非检查型异常。（ArithmeticException就是RuntimeException的子类。）通过捕获ArithmeticException和抛出DivideByZeroException，remainder()方法强迫它的调用者去处理除数为0的可能性，要么捕获它，要么在其throw子句中声明DivideByZeroException异常。这是因为，像DivideByZeroException这种在方法中抛出的检查型异常，要么在方法中捕获，要么在其throw子句中声明，二者必选其一。而像ArithmeticException这种非检查型异常，就不需要去显式捕获和声明。</p>
<p style="margin: 1rem 0px; padding: 0px; border: 0px; vertical-align: baseline; line-height: 24px; color: #444444; font-family: 'Open Sans', Helvetica, Arial, sans-serif;">javac为remainder()方法生成的字节码序列如下：</p>
<div no="" asm"="" style="margin: 0px 0px 1em; font-size: 11px; vertical-align: baseline; overflow: auto; white-space: nowrap; position: relative; font-family: monospace; color: #444444; background: #f3f3f3;">
<ol style="margin: 0px; padding: 0px 0px 0px 0em; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-style: none; vertical-align: baseline; list-style: none outside; line-height: 1.714285714;">
     <li style="margin: 0px 0px 0px 2.571428571rem; padding: 0px; border: 0px; vertical-align: baseline; list-style-type: none;">
     <div style="margin: 0px; padding-left: 5px; border: 0px; vertical-align: baseline; color: #000000; background: none;">// The main bytecode sequence&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #f63333;">for</span>&nbsp;remainder:</div>
     </li>
     <li style="margin: 0px 0px 0px 2.571428571rem; padding: 0px; border: 0px; vertical-align: baseline; list-style-type: none;">
     <div style="margin: 0px; padding-left: 5px; border: 0px; vertical-align: baseline; color: #000000; background: none;"><span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #ff33ff;">0</span>&nbsp;iload_0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #a1a100;">Push</span>&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #f63333;">local</span>&nbsp;variable&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #ff33ff;">0</span>&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #66cc66;">(</span>arg passed as divisor<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #66cc66;">)</span></div>
     </li>
     <li style="margin: 0px 0px 0px 2.571428571rem; padding: 0px; border: 0px; vertical-align: baseline; list-style-type: none;">
     <div style="margin: 0px; padding-left: 5px; border: 0px; vertical-align: baseline; color: #000000; background: none;"><span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #ff33ff;">1</span>&nbsp;iload_1 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #a1a100;">Push</span>&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #f63333;">local</span>&nbsp;variable&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #ff33ff;">1</span>&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #66cc66;">(</span>arg passed as dividend<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #66cc66;">)</span></div>
     </li>
     <li style="margin: 0px 0px 0px 2.571428571rem; padding: 0px; border: 0px; vertical-align: baseline; list-style-type: none;">
     <div style="margin: 0px; padding-left: 5px; border: 0px; vertical-align: baseline; color: #000000; background: none;"><span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #ff33ff;">2</span>&nbsp;irem &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;//&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #a1a100;">Pop</span>&nbsp;divisor,&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #a1a100;">pop</span>&nbsp;dividend,&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #a1a100;">push</span>&nbsp;remainder</div>
     </li>
     <li style="margin: 0px 0px 0px 2.571428571rem; padding: 0px; border: 0px; vertical-align: baseline; list-style-type: none;">
     <div style="margin: 0px; padding-left: 5px; border: 0px; vertical-align: baseline; color: #000000; background: none;"><span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #ff33ff;">3</span>&nbsp;ireturn &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Return&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #a1a100;">int</span>&nbsp;on top of&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #f63333;">stack</span>&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #66cc66;">(</span>the remainder<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #66cc66;">)</span></div>
     </li>
     <li style="margin: 0px 0px 0px 2.571428571rem; padding: 0px; border: 0px; vertical-align: baseline; list-style-type: none;">
     <div style="margin: 0px; padding-left: 5px; border: 0px; vertical-align: baseline; color: #000000; background: none;">// The bytecode sequence&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #f63333;">for</span>&nbsp;the catch&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #66cc66;">(</span>ArithmeticException<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #66cc66;">)</span>&nbsp;clause:</div>
     </li>
     <li style="margin: 0px 0px 0px 2.571428571rem; padding: 0px; border: 0px; vertical-align: baseline; list-style-type: none;">
     <div style="margin: 0px; padding-left: 5px; border: 0px; vertical-align: baseline; color: #000000; background: none;"><span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #ff33ff;">4</span>&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #a1a100;">pop</span>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #a1a100;">Pop</span>&nbsp;the reference to the ArithmeticException</div>
     </li>
     <li style="margin: 0px 0px 0px 2.571428571rem; padding: 0px; border: 0px; vertical-align: baseline; list-style-type: none;">
     <div style="margin: 0px; padding-left: 5px; border: 0px; vertical-align: baseline; color: #000000; background: none;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // because it is&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #a1a100;">not</span>&nbsp;used by&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #f63333;">this</span>&nbsp;catch clause.</div>
     </li>
     <li style="margin: 0px 0px 0px 2.571428571rem; padding: 0px; border: 0px; vertical-align: baseline; list-style-type: none;">
     <div style="margin: 0px; padding-left: 5px; border: 0px; vertical-align: baseline; color: #000000; background: none;"><span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #ff33ff;">5</span>&nbsp;new #<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #ff33ff;">5</span>&nbsp;&lt; Class DivideByZeroException &gt;</div>
     </li>
     <li style="margin: 0px 0px 0px 2.571428571rem; padding: 0px; border: 0px; vertical-align: baseline; list-style-type: none;">
     <div style="margin: 0px; padding-left: 5px; border: 0px; vertical-align: baseline; color: #000000; background: none;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Create&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #a1a100;">and</span>&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #a1a100;">push</span>&nbsp;reference to new object of class</div>
     </li>
     <li style="margin: 0px 0px 0px 2.571428571rem; padding: 0px; border: 0px; vertical-align: baseline; list-style-type: none;">
     <div style="margin: 0px; padding-left: 5px; border: 0px; vertical-align: baseline; color: #000000; background: none;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // DivideByZeroException.</div>
     </li>
     <li style="margin: 0px 0px 0px 2.571428571rem; padding: 0px; border: 0px; vertical-align: baseline; list-style-type: none;">
     <div style="margin: 0px; padding-left: 5px; border: 0px; vertical-align: baseline; color: #000000; background: none;"><span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #ff33ff;">8</span>&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #f63333;">dup</span>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Duplicate the reference to the new</div>
     </li>
     <li style="margin: 0px 0px 0px 2.571428571rem; padding: 0px; border: 0px; vertical-align: baseline; list-style-type: none;">
     <div style="margin: 0px; padding-left: 5px; border: 0px; vertical-align: baseline; color: #000000; background: none;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // object on the top of the&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #f63333;">stack</span>&nbsp;because it</div>
     </li>
     <li style="margin: 0px 0px 0px 2.571428571rem; padding: 0px; border: 0px; vertical-align: baseline; list-style-type: none;">
     <div style="margin: 0px; padding-left: 5px; border: 0px; vertical-align: baseline; color: #000000; background: none;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // must be both initialized</div>
     </li>
     <li style="margin: 0px 0px 0px 2.571428571rem; padding: 0px; border: 0px; vertical-align: baseline; list-style-type: none;">
     <div style="margin: 0px; padding-left: 5px; border: 0px; vertical-align: baseline; color: #000000; background: none;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #a1a100;">and</span>&nbsp;thrown. The initialization will consume</div>
     </li>
     <li style="margin: 0px 0px 0px 2.571428571rem; padding: 0px; border: 0px; vertical-align: baseline; list-style-type: none;">
     <div style="margin: 0px; padding-left: 5px; border: 0px; vertical-align: baseline; color: #000000; background: none;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // the copy of the reference created by the&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #f63333;">dup</span>.</div>
     </li>
     <li style="margin: 0px 0px 0px 2.571428571rem; padding: 0px; border: 0px; vertical-align: baseline; list-style-type: none;">
     <div style="margin: 0px; padding-left: 5px; border: 0px; vertical-align: baseline; color: #000000; background: none;"><span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #ff33ff;">9</span>&nbsp;invokenonvirtual #<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #ff33ff;">9</span>&nbsp;&lt; Method DivideByZeroException.&lt; init &gt;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #66cc66;">(</span><span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #66cc66;">)</span>V &gt;</div>
     </li>
     <li style="margin: 0px 0px 0px 2.571428571rem; padding: 0px; border: 0px; vertical-align: baseline; list-style-type: none;">
     <div style="margin: 0px; padding-left: 5px; border: 0px; vertical-align: baseline; color: #000000; background: none;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #a1a100;">Call</span>&nbsp;the constructor&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #f63333;">for</span>&nbsp;the DivideByZeroException</div>
     </li>
     <li style="margin: 0px 0px 0px 2.571428571rem; padding: 0px; border: 0px; vertical-align: baseline; list-style-type: none;">
     <div style="margin: 0px; padding-left: 5px; border: 0px; vertical-align: baseline; color: #000000; background: none;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // to initialize it.&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #f63333;">This</span>&nbsp;instruction</div>
     </li>
     <li style="margin: 0px 0px 0px 2.571428571rem; padding: 0px; border: 0px; vertical-align: baseline; list-style-type: none;">
     <div style="margin: 0px; padding-left: 5px; border: 0px; vertical-align: baseline; color: #000000; background: none;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // will&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #a1a100;">pop</span>&nbsp;the top reference to the object.</div>
     </li>
     <li style="margin: 0px 0px 0px 2.571428571rem; padding: 0px; border: 0px; vertical-align: baseline; list-style-type: none;">
     <div style="margin: 0px; padding-left: 5px; border: 0px; vertical-align: baseline; color: #000000; background: none;"><span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #ff33ff;">12</span>&nbsp;athrow &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #a1a100;">Pop</span>&nbsp;the reference to a Throwable object,&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #a1a100;">in</span>&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #f63333;">this</span></div>
     </li>
     <li style="margin: 0px 0px 0px 2.571428571rem; padding: 0px; border: 0px; vertical-align: baseline; list-style-type: none;">
     <div style="margin: 0px; padding-left: 5px; border: 0px; vertical-align: baseline; color: #000000; background: none;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // case the DivideByZeroException,</div>
     </li>
     <li style="margin: 0px 0px 0px 2.571428571rem; padding: 0px; border: 0px; vertical-align: baseline; list-style-type: none;">
     <div style="margin: 0px; padding-left: 5px; border: 0px; vertical-align: baseline; color: #000000; background: none;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: #a1a100;">and</span>&nbsp;throw the exception.</div>
     </li>
</ol>
</div>
<p style="margin: 1rem 0px; padding: 0px; border: 0px; vertical-align: baseline; line-height: 24px; color: #444444; font-family: 'Open Sans', Helvetica, Arial, sans-serif;">remainder()方法的字节码有2个单独的部分。第一部分是该方法的正常执行路径，这部分从第0行开始，到第3行结束。第二部分是从第4行开始，到12行结束的catch子句。</p>
<p style="margin: 1rem 0px; padding: 0px; border: 0px; vertical-align: baseline; line-height: 24px; color: #444444; font-family: 'Open Sans', Helvetica, Arial, sans-serif;">主字节码序列中的irem指令可能会抛出ArithmeticException异常。如果异常发生了，JVM通过在异常表中查找匹配的异常，它会知道要跳转到相应的异常处理的catch子句的字节码序列部分。每个捕获异常的方法，都跟类文件中与方法字节码一起交付的异常表关联。每一个捕获异常的try块，都是异常表中的一行。每行4条信息：开始行号（from）和结束行号（to），要跳转的字节码序列行号（target），被捕获的异常类的常量池索引（type）。remainder()方法的异常表如下所示：</p>
<table id="tablepress-26" tablepress-id-26"="" style="margin: 0px 0px 1.714285714rem; padding: 0px; border-style: none none solid; border-bottom-color: #ededed; font-size: 0.857142857rem; vertical-align: baseline; border-collapse: collapse; border-spacing: 0px; width: 652px; color: #757575; line-height: 24px; font-family: 'Open Sans', Helvetica, Arial, sans-serif;">
     <thead style="margin: 0px; padding: 0px; border: 0px; font-size: 12px; vertical-align: baseline;">
         <tr odd"="" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">
             <th style="margin: 0px; padding: 8px; border-bottom-width: 1px; border-style: none none solid; border-bottom-color: #dddddd; font-size: 0.785714286rem; vertical-align: middle; line-height: 2.181818182; text-transform: uppercase; color: #636363; background: 0px 0px #d9edf7;">
             <div style="margin: 0px; border: 0px; font-size: 11px; vertical-align: baseline;">FROM</div>
             </th><th style="margin: 0px; padding: 8px; border-bottom-width: 1px; border-style: none none solid; border-bottom-color: #dddddd; font-size: 0.785714286rem; vertical-align: middle; line-height: 2.181818182; text-transform: uppercase; color: #636363; background: 0px 0px #d9edf7;">
             <div style="margin: 0px; border: 0px; font-size: 11px; vertical-align: baseline;">TO</div>
             </th><th style="margin: 0px; padding: 8px; border-bottom-width: 1px; border-style: none none solid; border-bottom-color: #dddddd; font-size: 0.785714286rem; vertical-align: middle; line-height: 2.181818182; text-transform: uppercase; color: #636363; background: 0px 0px #d9edf7;">
             <div style="margin: 0px; border: 0px; font-size: 11px; vertical-align: baseline;">TARGET</div>
             </th><th style="margin: 0px; padding: 8px; border-bottom-width: 1px; border-style: none none solid; border-bottom-color: #dddddd; font-size: 0.785714286rem; vertical-align: middle; line-height: 2.181818182; text-transform: uppercase; color: #636363; float: none; background: 0px 0px #d9edf7;">
             <div style="margin: 0px; border: 0px; font-size: 11px; vertical-align: baseline;">TYPE</div>
             </th>
         </tr>
     </thead>
     <tbody style="margin: 0px; padding: 0px; border: 0px; font-size: 12px; vertical-align: baseline;">
         <tr even"="" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">
             <td style="margin: 0px; padding: 8px; border-top-width: 0px; border-right-style: none; border-bottom-style: none; border-left-style: none; vertical-align: top; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: 0px 0px; background-repeat: initial;">0</td>
             <td style="margin: 0px; padding: 8px; border-top-width: 0px; border-right-style: none; border-bottom-style: none; border-left-style: none; vertical-align: top; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: 0px 0px; background-repeat: initial;">4</td>
             <td style="margin: 0px; padding: 8px; border-top-width: 0px; border-right-style: none; border-bottom-style: none; border-left-style: none; vertical-align: top; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: 0px 0px; background-repeat: initial;">4</td>
             <td style="margin: 0px; padding: 8px; border-top-width: 0px; border-right-style: none; border-bottom-style: none; border-left-style: none; vertical-align: top; float: none; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: 0px 0px; background-repeat: initial;">&lt; Class java.lang.ArithmeticException &gt;</td>
         </tr>
     </tbody>
</table>
<p style="margin: 1rem 0px; padding: 0px; border: 0px; vertical-align: baseline; line-height: 24px; color: #444444; font-family: 'Open Sans', Helvetica, Arial, sans-serif;">上面的异常表表明，行号1到3范围内，ArithmeticException将被捕获。异常表中的&#8220;to&#8221;下面的结束行号始终比异常捕获的最大行号大1，上表中，结束行号为4，而异常捕获的最大行号是3。行号0到3的字节码序列对应remainder()方法中的try块。&#8220;target&#8221;列中，是行0到3的字节码发生ArithmeticException异常时要跳转到的目标行号。</p>
<p style="margin: 1rem 0px; padding: 0px; border: 0px; vertical-align: baseline; line-height: 24px; color: #444444; font-family: 'Open Sans', Helvetica, Arial, sans-serif;">如果方法执行过程中产生了异常，JVM会在异常表中查找匹配行。异常表中的匹配行要符合下面的条件：当前pc寄存器的值要在该行的表示范围之内，[from, to)，且产生的异常是该行所指定的异常类或其子类。JVM按从上到下的次序查找异常表。当找到了第一个匹配行，JVM把pc寄存器设为新的跳转行号，从此行继续往下执行。如果找不到匹配行，JVM弹出当前栈帧，并重新抛出同一个异常。当JVM弹出当前栈帧时，它会终止当前方法的执行，返回到调用该方法的上一个方法那里。这时，在上一个方法里，并不会继续正常的执行过程，而是抛出同样的异常，促使JVM重新查找该方法的异常表。</p>
<p style="margin: 1rem 0px; padding: 0px; border: 0px; vertical-align: baseline; line-height: 24px; color: #444444; font-family: 'Open Sans', Helvetica, Arial, sans-serif;">Java程序员可以用throw语句抛出像remainder()方法的catch子句中的异常，DivideByZeroException。下表列出了抛出异常的字节码：</p>
<table id="tablepress-27" tablepress-id-27"="" style="margin: 0px 0px 1.714285714rem; padding: 0px; border-style: none none solid; border-bottom-color: #ededed; font-size: 0.857142857rem; vertical-align: baseline; border-collapse: collapse; border-spacing: 0px; width: 652px; color: #757575; line-height: 24px; font-family: 'Open Sans', Helvetica, Arial, sans-serif;">
     <thead style="margin: 0px; padding: 0px; border: 0px; font-size: 12px; vertical-align: baseline;">
         <tr odd"="" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">
             <th style="margin: 0px; padding: 8px; border-bottom-width: 1px; border-style: none none solid; border-bottom-color: #dddddd; font-size: 0.785714286rem; vertical-align: middle; line-height: 2.181818182; text-transform: uppercase; color: #636363; background: 0px 0px #d9edf7;">
             <div style="margin: 0px; border: 0px; font-size: 11px; vertical-align: baseline;">OPCODE</div>
             </th><th style="margin: 0px; padding: 8px; border-bottom-width: 1px; border-style: none none solid; border-bottom-color: #dddddd; font-size: 0.785714286rem; vertical-align: middle; line-height: 2.181818182; text-transform: uppercase; color: #636363; background: 0px 0px #d9edf7;">
             <div style="margin: 0px; border: 0px; font-size: 11px; vertical-align: baseline;">OPERAND(S)</div>
             </th><th style="margin: 0px; padding: 8px; border-bottom-width: 1px; border-style: none none solid; border-bottom-color: #dddddd; font-size: 0.785714286rem; vertical-align: middle; line-height: 2.181818182; text-transform: uppercase; color: #636363; float: none; background: 0px 0px #d9edf7;">
             <div style="margin: 0px; border: 0px; font-size: 11px; vertical-align: baseline;">DESCRIPTION</div>
             </th>
         </tr>
     </thead>
     <tbody style="margin: 0px; padding: 0px; border: 0px; font-size: 12px; vertical-align: baseline;">
         <tr even"="" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">
             <td style="margin: 0px; padding: 8px; border-top-width: 0px; border-right-style: none; border-bottom-style: none; border-left-style: none; vertical-align: top; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: 0px 0px; background-repeat: initial;">athrow</td>
             <td style="margin: 0px; padding: 8px; border-top-width: 0px; border-right-style: none; border-bottom-style: none; border-left-style: none; vertical-align: top; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: 0px 0px; background-repeat: initial;">(none)</td>
             <td style="margin: 0px; padding: 8px; border-top-width: 0px; border-right-style: none; border-bottom-style: none; border-left-style: none; vertical-align: top; float: none; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: 0px 0px; background-repeat: initial;">pops Throwable object reference, throws the exception</td>
         </tr>
     </tbody>
</table>
<p style="margin: 1rem 0px; padding: 0px; border: 0px; vertical-align: baseline; line-height: 24px; color: #444444; font-family: 'Open Sans', Helvetica, Arial, sans-serif;">athrow指令把栈顶元素弹出，该元素必须是Throwable的子类或其自身的对象引用，而抛出的异常类型由栈顶弹出的对象引用所指明。</p>
<p style="margin: 1rem 0px; padding: 0px; border: 0px; vertical-align: baseline; line-height: 24px; color: #444444; font-family: 'Open Sans', Helvetica, Arial, sans-serif;">本文译自：<a href="http://www.javaworld.com/article/2076868/learn-java/how-the-java-virtual-machine-handles-exceptions.html" target="_blank" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; outline: none; color: #21759b;">How the Java virtual machine handles exceptions</a></p>
<div style="margin: 15px 0px 0px; border: 0px; vertical-align: baseline; color: #444444; font-family: 'Open Sans', Helvetica, Arial, sans-serif; line-height: 24px;">
<p style="margin: 1rem 0px; padding: 0px; border: 0px; vertical-align: baseline; line-height: 1.714285714;"><strong style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">本文出自：</strong><a href="http://letscoding.cn/" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; outline: none; color: #21759b;">码农合作社</a>&nbsp;》<a href="http://letscoding.cn/jvm%e4%b8%ad%e7%9a%84%e5%bc%82%e5%b8%b8%e5%a4%84%e7%90%86/" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; outline: none; color: #21759b;">JVM中的异常处理</a>，转载请注明。</p>
</div>
<img src ="http://www.blogjava.net/4cai/aggbug/414314.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/4cai/" target="_blank">Rolandz</a> 2014-06-02 03:54 <a href="http://www.blogjava.net/4cai/archive/2014/06/02/414314.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>对象和数组：JVM中，处理对象和数组的字节码介绍</title><link>http://www.blogjava.net/4cai/archive/2014/05/30/414259.html</link><dc:creator>Rolandz</dc:creator><author>Rolandz</author><pubDate>Thu, 29 May 2014 18:14:00 GMT</pubDate><guid>http://www.blogjava.net/4cai/archive/2014/05/30/414259.html</guid><wfw:comment>http://www.blogjava.net/4cai/comments/414259.html</wfw:comment><comments>http://www.blogjava.net/4cai/archive/2014/05/30/414259.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/4cai/comments/commentRss/414259.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/4cai/services/trackbacks/414259.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 欢迎来到&#8220;Under The Hood&#8221;第五期。本期我们来看看JVM中处理对象和数组的字节码。你可能需要阅读往期的文章才能更好的理解本文。面向对象的机器JVM中的数据有3种形式：对象（object），对象引用（object reference）和原始类型（primitive type）。对象存放在垃圾收集堆中；对象引用和原始类型，根据它们作用域范围的不同，分别存放在...&nbsp;&nbsp;<a href='http://www.blogjava.net/4cai/archive/2014/05/30/414259.html'>阅读全文</a><img src ="http://www.blogjava.net/4cai/aggbug/414259.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/4cai/" target="_blank">Rolandz</a> 2014-05-30 02:14 <a href="http://www.blogjava.net/4cai/archive/2014/05/30/414259.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>初窥JVM浮点运算</title><link>http://www.blogjava.net/4cai/archive/2014/05/26/414118.html</link><dc:creator>Rolandz</dc:creator><author>Rolandz</author><pubDate>Mon, 26 May 2014 07:09:00 GMT</pubDate><guid>http://www.blogjava.net/4cai/archive/2014/05/26/414118.html</guid><wfw:comment>http://www.blogjava.net/4cai/comments/414118.html</wfw:comment><comments>http://www.blogjava.net/4cai/archive/2014/05/26/414118.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/4cai/comments/commentRss/414118.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/4cai/services/trackbacks/414118.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: JVM支持IEEE-754浮点数标准（1985）。该标准定义了32位和64位浮点数的格式，以及在此之上的各种运算。在JVM中，浮点运算是基于32位float数和64位double数的。对每个操作float数的字节码，都有一个对应的操作double数的版本。&nbsp;&nbsp;<a href='http://www.blogjava.net/4cai/archive/2014/05/26/414118.html'>阅读全文</a><img src ="http://www.blogjava.net/4cai/aggbug/414118.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/4cai/" target="_blank">Rolandz</a> 2014-05-26 15:09 <a href="http://www.blogjava.net/4cai/archive/2014/05/26/414118.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>字节码基础：JVM字节码初探</title><link>http://www.blogjava.net/4cai/archive/2014/05/22/413950.html</link><dc:creator>Rolandz</dc:creator><author>Rolandz</author><pubDate>Wed, 21 May 2014 18:07:00 GMT</pubDate><guid>http://www.blogjava.net/4cai/archive/2014/05/22/413950.html</guid><wfw:comment>http://www.blogjava.net/4cai/comments/413950.html</wfw:comment><comments>http://www.blogjava.net/4cai/archive/2014/05/22/413950.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.blogjava.net/4cai/comments/commentRss/413950.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/4cai/services/trackbacks/413950.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 字节码是JVM的机器语言。JVM加载类文件时，对类中的每个方法，它都会得到一个字节码流。这些字节码流保存在JVM的方法区中。在程序运行过程中，当一个方法被调用时，它的字节码流就会被执行。根据特定JVM设计者的选择，它们可以通过解释的方式，即时编译（Just-in-time compilation）的方式或其他技术的方式被执行。&nbsp;&nbsp;<a href='http://www.blogjava.net/4cai/archive/2014/05/22/413950.html'>阅读全文</a><img src ="http://www.blogjava.net/4cai/aggbug/413950.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/4cai/" target="_blank">Rolandz</a> 2014-05-22 02:07 <a href="http://www.blogjava.net/4cai/archive/2014/05/22/413950.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java类文件的基本结构</title><link>http://www.blogjava.net/4cai/archive/2014/05/19/413821.html</link><dc:creator>Rolandz</dc:creator><author>Rolandz</author><pubDate>Sun, 18 May 2014 19:49:00 GMT</pubDate><guid>http://www.blogjava.net/4cai/archive/2014/05/19/413821.html</guid><wfw:comment>http://www.blogjava.net/4cai/comments/413821.html</wfw:comment><comments>http://www.blogjava.net/4cai/archive/2014/05/19/413821.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/4cai/comments/commentRss/413821.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/4cai/services/trackbacks/413821.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: Java类文件（.class文件）是一个为已编译Java程序仔细定义的格式。Java源代码被编译成能够被任何JVM加载和执行的类文件。在被JVM加载之前，类文件可能是由网络传输而来。类文件是独立于底层平台的，所以适用于更多的地方。它们由简洁的JVM字节码组成，这样就能轻装上阵。类文件常常被压缩，以极快的速度通过网络，到达世界各地的JVM。&nbsp;&nbsp;<a href='http://www.blogjava.net/4cai/archive/2014/05/19/413821.html'>阅读全文</a><img src ="http://www.blogjava.net/4cai/aggbug/413821.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/4cai/" target="_blank">Rolandz</a> 2014-05-19 03:49 <a href="http://www.blogjava.net/4cai/archive/2014/05/19/413821.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>短小精悍的虚拟机：JVM基本结构和功能介绍</title><link>http://www.blogjava.net/4cai/archive/2014/05/17/413789.html</link><dc:creator>Rolandz</dc:creator><author>Rolandz</author><pubDate>Sat, 17 May 2014 13:50:00 GMT</pubDate><guid>http://www.blogjava.net/4cai/archive/2014/05/17/413789.html</guid><wfw:comment>http://www.blogjava.net/4cai/comments/413789.html</wfw:comment><comments>http://www.blogjava.net/4cai/archive/2014/05/17/413789.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/4cai/comments/commentRss/413789.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/4cai/services/trackbacks/413789.html</trackback:ping><description><![CDATA[<em>欢迎来到&#8220;<a href="http://letscoding.cn/tag/under-the-hood/"><span style="color: #0000ff;">Under The Hood</span></a>&#8221;第一期。本期，我将给出JVM的基本结构和功能介绍。
</em>
<p style="margin: 1rem 0px; padding: 0px; border: 0px; vertical-align: baseline; line-height: 1.714285714;"><em style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;"><strong style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">什么是JVM？为什么要有它？</strong></em></p>
<p style="margin: 1rem 0px; padding: 0px; border: 0px; vertical-align: baseline; line-height: 1.714285714;">JVM（Java虚拟机）是一个运行已编译Java程序的抽象计算机。之所以说是&#8221;虚拟&#8220;的，是因为它基于&#8220;真正&#8221;的硬件平台和操作系统，一般以软件的形式实现。所有的Java程序都为JVM而编译。因此，在特定平台上运行已编译Java程序之前，该平台的JVM必须先要被实现。</p>
<p style="margin: 1rem 0px; padding: 0px; border: 0px; vertical-align: baseline; line-height: 1.714285714;">JVM在Java的跨平台特性中，起着中间人的角色。它在已编译Java程序与底层硬件平台和操作系统之间，提供一个抽象层。JVM对Java的可移植性非常关键，因为，已编译Java程序运行在JVM之上，并独立于底层JVM的具体实现。</p>
<p style="margin: 1rem 0px; padding: 0px; border: 0px; vertical-align: baseline; line-height: 1.714285714;">那么，是什么导致JVM的短小精悍？当被实现成软件时，JMV很小巧。它被设计成这样，是为了让它能够适用于尽可能多的地方，比如机顶盒，手机和个人电脑。JVM很精悍，是因为它的野心。&#8221;无处不在！&#8220;是它的战斗口号。它想要无处不在，并且Java程序&#8221;一次编写，到处运行&#8220;的程度说明了它的成功。<br />
</p>
<p style="margin: 1rem 0px; padding: 0px; border: 0px; vertical-align: baseline; line-height: 1.714285714;"><em style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;"><strong style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">Java字节码</strong></em></p>
<p style="margin: 1rem 0px; padding: 0px; border: 0px; vertical-align: baseline; line-height: 1.714285714;">Java程序被编译成一种叫做字节码的东东。JVM执行Java字节码，所以字节码可以被认为是JVM的机器语言。Java编译器读取Java源文件，把它翻译成Java字节码并保存到类文件（.class文件）中。编译器会为源码中的每一个类生成一个类文件。</p>
<p style="margin: 1rem 0px; padding: 0px; border: 0px; vertical-align: baseline; line-height: 1.714285714;">对JVM来说，字节码流就是指令序列。每条指令包含一个单字节的操作码和零个或多个操作数。操作码告诉JVM要执行的操作。如果JVM需要除操作码之外更多的信息去执行一项操作，那么，需要的信息作为操作数，紧跟在操作码之后。</p>
<p style="margin: 1rem 0px; padding: 0px; border: 0px; vertical-align: baseline; line-height: 1.714285714;">每个字节码都有一个助记符，它可被当作JVM的汇编语言。例如，有个指令会让JVM把0压到堆栈中。该指令的助记符是iconst_0，字节码值是0&#215;60。该指令没有操作数。另一个指令让程序的执行在内存中无条件向前向后跳转。这个指令需要一个操作数，它是一个指明从当前内存地址开始的2字节无符号偏移量。通过把偏移量加到当前内存地址，JVM可以获得要跳转的目标内存地址。该指令的助记符是goto，它的字节码值是0xa7。</p>
<p style="margin: 1rem 0px; padding: 0px; border: 0px; vertical-align: baseline; line-height: 1.714285714;"><em style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;"><strong style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">虚拟部分</strong></em></p>
<p style="margin: 1rem 0px; padding: 0px; border: 0px; vertical-align: baseline; line-height: 1.714285714;">JVM的&#8220;虚拟硬件&#8221;可以分为四个部分：寄存器组，栈区，垃圾收集堆和方法区。这些部分很抽象，就像由它们组成的虚拟机一样；但是它们必须在每个JVM的实现中，以某种形式存在。</p>
<p style="margin: 1rem 0px; padding: 0px; border: 0px; vertical-align: baseline; line-height: 1.714285714;">JVM中地址的是32位（4字节）的，因此，JVM可以处理4GB（2的32次方）的内存。栈区，垃圾收集堆和方法区处在这4GB内存中的某个地方，至于它们的具体内存地址，这取决于每个特定JVM的实现者。</p>
<p style="margin: 1rem 0px; padding: 0px; border: 0px; vertical-align: baseline; line-height: 1.714285714;">JVM中一个字（word）的长度是32位的。JVM中有少数几个原始数据类型：byte（8位），short（16位），int（32位），long（64位），float（32位），double（64位），char（16位）。除了无符号Unicode字符char之外，其他6种数字类型都是有符号的。这些类型可以方便的映射到Java程序员可用的数据类型。另一个原始类型是对象句柄，它是一个指向堆中对象的32位地址。</p>
<p style="margin: 1rem 0px; padding: 0px; border: 0px; vertical-align: baseline; line-height: 1.714285714;">由于包含字节码，方法区以字节边界对齐。栈和垃圾收集堆以字（32位）边界对齐<span style="margin: 0px; padding: 0px; border: 0px; font-size: 11px; vertical-align: baseline; line-height: 0; position: relative; top: -0.5em;">1</span>。</p>
<p style="margin: 1rem 0px; padding: 0px; border: 0px; vertical-align: baseline; line-height: 1.714285714;"><em style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;"><strong style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">寄存器：我少我自豪</strong></em></p>
<p style="margin: 1rem 0px; padding: 0px; border: 0px; vertical-align: baseline; line-height: 1.714285714;">JVM有1个程序计数器（counter）和3个管理栈的寄存器（register）。它只有很少的寄存器，是因为JVM字节码指令主要操作栈区。这种面向栈的设计，使得JVM指令集和JVM实现很小巧。</p>
<p style="margin: 1rem 0px; padding: 0px; border: 0px; vertical-align: baseline; line-height: 1.714285714;">JVM使用程序计数器（也叫pc寄存器），跟踪当前执行指令的内存位置。另外3个寄存器（optop寄存器，frame寄存器和vars寄存器）指向当前执行方法栈帧上不同的部位。执行方法的栈帧持有特定方法调用的状态（本地变量，即时计算结果等）。</p>
<p style="margin: 1rem 0px; padding: 0px; border: 0px; vertical-align: baseline; line-height: 1.714285714;"><em style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;"><strong style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">方法区和程序计数器</strong></em></p>
<p style="margin: 1rem 0px; padding: 0px; border: 0px; vertical-align: baseline; line-height: 1.714285714;">方法区是字节码呆的地方。程序计数器跟踪执行线程。当前字节码指令执行后，程序计数器会包含下一条执行指令的地址：一条指令执行之后，JVM把程序计数器设置为紧跟上一条指令的指令地址，除非上一条指令具体指明一次跳转。</p>
<p style="margin: 1rem 0px; padding: 0px; border: 0px; vertical-align: baseline; line-height: 1.714285714;"><em style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;"><strong style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">Java栈和相关寄存器</strong></em></p>
<p style="margin: 1rem 0px; padding: 0px; border: 0px; vertical-align: baseline; line-height: 1.714285714;">Java栈用来保存字节码指令的参数和执行结果，给方法传递参数和返回结果，保存每个方法调用的状态。方法调用的状态被称为调用栈帧。var寄存器，frame寄存器和optop寄存器指向当前栈帧的不同部位。</p>
<p style="margin: 1rem 0px; padding: 0px; border: 0px; vertical-align: baseline; line-height: 1.714285714;">Java栈帧有3个区：本地变量，执行环境和操作数栈。本地变量区，包含当前方法调用中使用的所有本地变量。它由vars寄存器指向。执行环境区用来维护栈区本身的操作。它被frame寄存器指向。操作数区用来作为字码指令的工作区。正是在这里，存放着字节码指令的参数和其返回结果。操作数栈区的顶部被optop寄存器指向。</p>
<p style="margin: 1rem 0px; padding: 0px; border: 0px; vertical-align: baseline; line-height: 1.714285714;">执行环境通常夹在本地变量和操作数栈中间。当前执行方法的操作数栈总是在栈区的最上面，所以optop寄存器总是指向整个Java栈的顶部。</p>
<p style="margin: 1rem 0px; padding: 0px; border: 0px; vertical-align: baseline; line-height: 1.714285714;"><em style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;"><strong style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">垃圾收集堆</strong></em></p>
<p style="margin: 1rem 0px; padding: 0px; border: 0px; vertical-align: baseline; line-height: 1.714285714;">堆是Java对象生存的地方。任何时候，你用new操作符分配的内存，都来自堆中。Java语言不允许你直接释放分配的内存。运行时环境会跟踪堆上每个对象的引用，自动释放那些不被引用的对象所占据的内存，这个过程被称为垃圾收集。</p>
<p style="margin: 1rem 0px; padding: 0px; border: 0px; vertical-align: baseline; line-height: 1.714285714;"><em style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;"><strong style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">参考</strong></em></p>
<ol style="margin: 0px 0px 1.714285714rem; padding: 0px; border: 0px; vertical-align: baseline; list-style-position: outside; list-style-image: initial; line-height: 1.714285714;">
     <li style="margin: 0px 0px 0px 2.571428571rem; padding: 0px; border: 0px; vertical-align: baseline;">关于内存对齐方式，请参考<a href="https://www.ibm.com/developerworks/library/pa-dalign/" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; outline: none; color: #9f9f9f;">Data alignment: Straighten up and fly right</a>。</li>
</ol>
<p style="margin: 1rem 0px; padding: 0px; border: 0px; vertical-align: baseline; line-height: 1.714285714;">本文译自：<a href="http://www.javaworld.com/article/2077184/core-java/the-lean--mean--virtual-machine.html" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; outline: none; color: #9f9f9f;">The lean, mean, virtual machine</a></p>
<p style="margin: 1rem 0px; padding: 0px; border: 0px; vertical-align: baseline; line-height: 1.714285714;"><strong style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">原创文章，转载请注明：</strong>&nbsp;转载自<a href="http://letscoding.cn/" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; outline: none; color: #9f9f9f;"><span style="color: #0000ff;">LetsCoding.cn</span></a><br />
<strong style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">本文链接地址:</strong>&nbsp;<a href="http://letscoding.cn/%e7%9f%ad%e5%b0%8f%e7%b2%be%e6%82%8d%e7%9a%84%e8%99%9a%e6%8b%9f%e6%9c%ba%ef%bc%9ajvm%e5%9f%ba%e6%9c%ac%e7%bb%93%e6%9e%84%e5%92%8c%e5%8a%9f%e8%83%bd%e4%bb%8b%e7%bb%8d/" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; outline: none; color: #9f9f9f;"><span style="color: #0000ff;">短小精悍的虚拟机：JVM基本结构和功能介绍</span></a></p><img src ="http://www.blogjava.net/4cai/aggbug/413789.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/4cai/" target="_blank">Rolandz</a> 2014-05-17 21:50 <a href="http://www.blogjava.net/4cai/archive/2014/05/17/413789.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java中，状态模式和策略模式的区别</title><link>http://www.blogjava.net/4cai/archive/2014/05/16/413717.html</link><dc:creator>Rolandz</dc:creator><author>Rolandz</author><pubDate>Thu, 15 May 2014 19:23:00 GMT</pubDate><guid>http://www.blogjava.net/4cai/archive/2014/05/16/413717.html</guid><wfw:comment>http://www.blogjava.net/4cai/comments/413717.html</wfw:comment><comments>http://www.blogjava.net/4cai/archive/2014/05/16/413717.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/4cai/comments/commentRss/413717.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/4cai/services/trackbacks/413717.html</trackback:ping><description><![CDATA[<span style="font-size: 12pt; font-family: Arial;">本文转自：<a href="http://letscoding.cn"><span style="color: #3366ff;">码农合作社</span></a>的</span><a href="http://letscoding.cn/java%E4%B8%AD%EF%BC%8C%E7%8A%B6%E6%80%81%E6%A8%A1%E5%BC%8F%E5%92%8C%E7%AD%96%E7%95%A5%E6%A8%A1%E5%BC%8F%E7%9A%84%E5%8C%BA%E5%88%AB/" target="_blank"><span style="font-size: 12pt; color: #3366ff;">Java中，状态模式和策略模式的区别</span></a><span style="font-size: 12pt; font-family: Arial;"><br /></span><span style="font-size: 12pt; font-family: Arial;"><br />Ja</span><span style="font-size: 12pt; font-family: Arial;">va开发者，要想恰</span><span style="font-size: 12pt; font-family: Arial;">当的使用状态模式和策略模式，必须清楚的理解它们之间的区别。虽然状态模式和策略模式拥有相似的结构，虽然它们都基于</span><a href="http://en.wikipedia.org/wiki/SOLID_(object-oriented_design)" style="line-height: 1.714285714; font-size: 14px; margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; outline: none; color: #9f9f9f;"><span style="font-size: 12pt; font-family: Arial;">SOLID设计原则</span></a><span style="line-height: 1.714285714; font-size: 12pt; font-family: Arial;">中的O（开闭原则），但是，它们的意图是完全不同的。</span>
<p style="margin: 1rem 0px; padding: 0px; border: 0px; vertical-align: baseline; line-height: 1.714285714;"><span style="font-size: 12pt; font-family: Arial;">策略模式通过封装一组相关算法，为Client提供运行时的灵活性。Client可以在运行时，选择任一算法，而不改变使用算法的Context。一些流行的策略模式的例子是写那些使用算法的代码，例如加密算法、压缩算法、排序算法。另一方面，状态模式允许对象，在不同的状态拥有不同的行为。因为现实世界中的对象通常都是有状态的，所以它们在不同状态，行为也不一样。例如，VM（自动售货机）只在hasCoin状态才给你吐商品；你不投币，它是不会吐的。现在你可以清楚的看出它们的不同之处了：它们的意图是不同的。状态模式帮助对象管理状态，而策略模式允许Client选择不同的行为。</span><br />
</p>
<p style="margin: 1rem 0px; padding: 0px; border: 0px; vertical-align: baseline; line-height: 1.714285714;"><span style="font-size: 12pt; font-family: Arial;">另一个不那么容易能看出来的区别是：是谁促使了行为的改变。策略模式中，是Client提供了不同的策略给Context；状态模式中，状态转移由Context或State自己管理。另外，如果你在State中管理状态转移，那么它必须持有Context的引用。例如，在VM的例子中，State对象需要调用VM的setState()方法去改变它的状态。另一方面，Strategy从不持有Context的引用，是Client把所选择的Strategy传递给Context。由于状态模式和策略模式的区别，是流行的Java设计原则类面试题之一，我们将会在本文探讨在Java中，状态模式和策略模式的异同，这可以加深你对它们的理解。</span></p>
<p style="margin: 1rem 0px; padding: 0px; border: 0px; vertical-align: baseline; line-height: 1.714285714;"><em style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; font-size: 14pt; font-family: Arial;"><strong style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">相似之处</strong></em></p><p style="margin: 1rem 0px; padding: 0px; border: 0px; vertical-align: baseline; line-height: 1.714285714;"><span style="font-size: 12pt; font-family: Arial;">如果你看看状态模式和策略模式的UML图，就会发现它们的结构非常相似。使用State对象改变自己行为的对象被称为Context对象；相似的，使用Strategy对象改变自己行为的对象叫Context对象。记住，Client和Context打交道。在状态模式中，Context把方法调用委托给当前的状态对象，而在策略模式中，Context使用的Strategy对象，是被当做参数传递过来的，或在Context对象被创建时就被提供的。</span></p>
<p style="margin: 1rem 0px; padding: 0px; border: 0px; vertical-align: baseline; line-height: 1.714285714;"><img src="http://letscoding.cn/images/State%20Design%20Pattern.png" alt="状态模式UML类图" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; max-width: 100%; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; box-shadow: rgba(0, 0, 0, 0.2) 0px 1px 4px;" /></p>
<p style="margin: 1rem 0px; padding: 0px; border: 0px; vertical-align: baseline; line-height: 1.714285714;"><span style="font-size: 12pt; font-family: Arial;">这是专为经典的VM问题而设计的状态模式UML类图。你可以看出，VM的状态是个接口，它有表示不同状态的具体实现。每一个状态都持有Context的引用，用它来管理由Context触发的行为导致的状态转移。</span></p>
<p style="margin: 1rem 0px; padding: 0px; border: 0px; vertical-align: baseline; line-height: 1.714285714;"><img src="http://letscoding.cn/images/Strategy%20Design%20Pattern%20in%20Java.png" alt="策略模式UML类图" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; max-width: 100%; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; box-shadow: rgba(0, 0, 0, 0.2) 0px 1px 4px;" /></p>
<p style="margin: 1rem 0px; padding: 0px; border: 0px; vertical-align: baseline; line-height: 1.714285714;"><span style="font-size: 12pt; font-family: Arial;">这是专为实现排序功能而设计的策略模式UML类图。因为存在很多排序算法，该模式让Client在排序时选择适当的算法。事实上，Java的集合框架就使用这个模式，实现了用来排序的Collections.sort()方法。不同的是，它不允许Client选择排序算法，而是让它传递Comparator或Comparable接口的实例来指定比较策略。</span></p>
<p style="margin: 1rem 0px; padding: 0px; border: 0px; vertical-align: baseline; line-height: 1.714285714;"><span style="font-size: 12pt; font-family: Arial;">让我们来看看它们之间更多的相似之处：</span></p>
<ol style="margin: 0px 0px 1.714285714rem; padding: 0px; border: 0px; vertical-align: baseline; list-style-position: outside; list-style-image: initial; line-height: 1.714285714;">
     <li style="margin: 0px 0px 0px 2.571428571rem; padding: 0px; border: 0px; vertical-align: baseline;"><span style="font-size: 12pt; font-family: Arial;">添加新的状态或策略都很容易，而且不需要修改使用它们的Context对象。</span></li>
     <li style="margin: 0px 0px 0px 2.571428571rem; padding: 0px; border: 0px; vertical-align: baseline;"><span style="font-size: 12pt; font-family: Arial;">它们都让你的代码符合OCP原则。在状态模式和策略模式中，Context对象对修改是关闭的，添加新的状态或策略，都不需要修改Context。</span></li>
     <li style="margin: 0px 0px 0px 2.571428571rem; padding: 0px; border: 0px; vertical-align: baseline;"><span style="font-size: 12pt; font-family: Arial;">正如状态模式中的Context会有初始状态一样，策略模式同样有默认策略。</span></li>
     <li style="margin: 0px 0px 0px 2.571428571rem; padding: 0px; border: 0px; vertical-align: baseline;"><span style="font-size: 12pt; font-family: Arial;">状态模式以不同的状态封装不同的行为，而策略模式以不同的策略封装不同的行为。</span></li>
     <li style="margin: 0px 0px 0px 2.571428571rem; padding: 0px; border: 0px; vertical-align: baseline;"><span style="font-size: 12pt; font-family: Arial;">它们都依赖子类去实现相关行为。</span></li>
</ol>
<p style="margin: 1rem 0px; padding: 0px; border: 0px; vertical-align: baseline; line-height: 1.714285714;"><em style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; font-size: 14pt; font-family: Arial;"><strong style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">不同之处</strong></em></p>
<p style="margin: 1rem 0px; padding: 0px; border: 0px; vertical-align: baseline; line-height: 1.714285714;"><span style="font-size: 12pt; font-family: Arial;">现在我们知道，状态模式和策略模式的结构是相似的，但它们的意图不同。让我们重温一下它们的主要不同之处：</span></p>
<ol style="margin: 0px 0px 1.714285714rem; padding: 0px; border: 0px; vertical-align: baseline; list-style-position: outside; list-style-image: initial; line-height: 1.714285714;">
     <li style="margin: 0px 0px 0px 2.571428571rem; padding: 0px; border: 0px; vertical-align: baseline;"><span style="font-size: 12pt; font-family: Arial;">策略模式封装了一组相关算法，它允许Client在运行时使用可互换的行为；状态模式帮助一个类在不同的状态显示不同的行为。</span></li>
     <li style="margin: 0px 0px 0px 2.571428571rem; padding: 0px; border: 0px; vertical-align: baseline;"><span style="font-size: 12pt; font-family: Arial;">状态模式封装了对象的状态，而策略模式封装算法或策略。因为状态是跟对象密切相关的，它不能被重用；而通过从Context中分离出策略或算法，我们可以重用它们。</span></li>
     <li style="margin: 0px 0px 0px 2.571428571rem; padding: 0px; border: 0px; vertical-align: baseline;"><span style="font-size: 12pt; font-family: Arial;">在状态模式中，每个状态通过持有Context的引用，来实现状态转移；但是每个策略都不持有Context的引用，它们只是被Context使用。</span></li>
     <li style="margin: 0px 0px 0px 2.571428571rem; padding: 0px; border: 0px; vertical-align: baseline;"><span style="font-size: 12pt; font-family: Arial;">策略实现可以作为参数传递给使用它的对象，例如Collections.sort()，它的参数包含一个Comparator策略。另一方面，状态是Context对象自己的一部分，随着时间的推移，Context对象从一个状态转移到另一个状态。</span></li>
     <li style="margin: 0px 0px 0px 2.571428571rem; padding: 0px; border: 0px; vertical-align: baseline;"><span style="font-size: 12pt; font-family: Arial;">虽然它们都符合OCP原则，策略模式也符合SRP原则（单一职责原则），因为每个策略都封装自己的算法，且不依赖其他策略。一个策略的改变，并不会导致其他策略的变化。</span></li>
     <li style="margin: 0px 0px 0px 2.571428571rem; padding: 0px; border: 0px; vertical-align: baseline;"><span style="font-size: 12pt; font-family: Arial;">另一个理论上的不同：策略模式定义了对象&#8220;怎么做&#8221;的部分。例如，排序对象怎么对数据排序。状态模式定义了对象&#8220;是什么&#8221;和&#8220;什么时候做&#8221;的部分。例如，对象处于什么状态，什么时候处在某个特定的状态。</span></li>
     <li style="margin: 0px 0px 0px 2.571428571rem; padding: 0px; border: 0px; vertical-align: baseline;"><span style="font-size: 12pt; font-family: Arial;">状态模式中很好的定义了状态转移的次序；而策略模式并无此需要：Client可以自由的选择任何策略。</span></li>
     <li style="margin: 0px 0px 0px 2.571428571rem; padding: 0px; border: 0px; vertical-align: baseline;"><span style="font-size: 12pt; font-family: Arial;">一些常见的策略模式的例子是封装算法，例如排序算法，加密算法或者压缩算法。如果你看到你的代码需要使用不同类型的相关算法，那么考虑使用策略模式吧。而识别何时使用状态模式是很简单的：如果你需要管理状态和状态转移，但不想使用大量嵌套的条件语句，那么就是它了。</span></li>
     <li style="margin: 0px 0px 0px 2.571428571rem; padding: 0px; border: 0px; vertical-align: baseline;"><span style="font-size: 12pt; font-family: Arial;">最后但最重要的一个不同之处是，策略的改变由Client完成；而状态的改变，由Context或状态自己。</span></li>
</ol>
<p style="margin: 1rem 0px; padding: 0px; border: 0px; vertical-align: baseline; line-height: 1.714285714;"><span style="font-size: 12pt; font-family: Arial;">本文译自：</span><a href="http://javarevisited.blogspot.com/2014/04/difference-between-state-and-strategy-design-pattern-java.html" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; outline: none; color: #9f9f9f;"><span style="font-size: 12pt; font-family: Arial;">Difference between State and Strategy Design Pattern in Java</span></a></p>
<p style="margin: 1rem 0px; padding: 0px; border: 0px; vertical-align: baseline; line-height: 1.714285714;"><strong style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; font-size: 12pt; font-family: Arial;">原创文章，转载请注明：</strong><span style="font-size: 12pt; font-family: Arial;">&nbsp;转载自</span><a href="http://letscoding.cn/" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; outline: none; color: #9f9f9f; font-size: 12pt; font-family: Arial;"><span style="color: #0000ff;">LetsCoding.cn</span></a><br style="font-size: 12pt; font-family: Arial;" /><span style="font-size: 12pt; font-family: Arial;">
</span><strong style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; font-size: 12pt; font-family: Arial;">本文链接地址:</strong><span style="font-size: 12pt; font-family: Arial;">&nbsp;</span><a href="http://letscoding.cn/java%e4%b8%ad%ef%bc%8c%e7%8a%b6%e6%80%81%e6%a8%a1%e5%bc%8f%e5%92%8c%e7%ad%96%e7%95%a5%e6%a8%a1%e5%bc%8f%e7%9a%84%e5%8c%ba%e5%88%ab/" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; outline: none; color: #9f9f9f; font-size: 12pt; font-family: Arial;"><span style="color: #0000ff;">Java中，状态模式和策略模式的区别</span></a></p><img src ="http://www.blogjava.net/4cai/aggbug/413717.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/4cai/" target="_blank">Rolandz</a> 2014-05-16 03:23 <a href="http://www.blogjava.net/4cai/archive/2014/05/16/413717.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java 8：Lambda表达式（二）</title><link>http://www.blogjava.net/4cai/archive/2014/05/11/413510.html</link><dc:creator>Rolandz</dc:creator><author>Rolandz</author><pubDate>Sun, 11 May 2014 04:07:00 GMT</pubDate><guid>http://www.blogjava.net/4cai/archive/2014/05/11/413510.html</guid><wfw:comment>http://www.blogjava.net/4cai/comments/413510.html</wfw:comment><comments>http://www.blogjava.net/4cai/archive/2014/05/11/413510.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/4cai/comments/commentRss/413510.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/4cai/services/trackbacks/413510.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: Java 8中，最重要的一个改变让代码更快、更简洁，并向FP（函数式编程）打开了方便之门。下面我们来看看，它是如何做到的。上一篇中，你看到了Java中Lambda表达式的一种形式：参数 + &#8220;-&gt;&#8221; + 表达式。如果代码实现的逻辑一条语句完成不了，你可以写成类似方法的形式：代码写在&#8220;{}&#8221;中，再加上显式的return语句。例如：...&nbsp;&nbsp;<a href='http://www.blogjava.net/4cai/archive/2014/05/11/413510.html'>阅读全文</a><img src ="http://www.blogjava.net/4cai/aggbug/413510.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/4cai/" target="_blank">Rolandz</a> 2014-05-11 12:07 <a href="http://www.blogjava.net/4cai/archive/2014/05/11/413510.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java 8：Lambda表达式（三）</title><link>http://www.blogjava.net/4cai/archive/2014/05/11/413511.html</link><dc:creator>Rolandz</dc:creator><author>Rolandz</author><pubDate>Sun, 11 May 2014 04:07:00 GMT</pubDate><guid>http://www.blogjava.net/4cai/archive/2014/05/11/413511.html</guid><wfw:comment>http://www.blogjava.net/4cai/comments/413511.html</wfw:comment><comments>http://www.blogjava.net/4cai/archive/2014/05/11/413511.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/4cai/comments/commentRss/413511.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/4cai/services/trackbacks/413511.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: Java 8中，最重要的一个改变让代码更快、更简洁，并向FP（函数式编程）打开了方便之门。下面我们来看看，它是如何做到的。变量作用域你经常会想，如果可以在Lambda表达式里访问外部方法或类中变量就好了。看下面的例子：          public&nbsp;static&nbsp;void&nbsp;repeatMessage(String&nbsp;text,&nbs...&nbsp;&nbsp;<a href='http://www.blogjava.net/4cai/archive/2014/05/11/413511.html'>阅读全文</a><img src ="http://www.blogjava.net/4cai/aggbug/413511.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/4cai/" target="_blank">Rolandz</a> 2014-05-11 12:07 <a href="http://www.blogjava.net/4cai/archive/2014/05/11/413511.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>