??xml version="1.0" encoding="utf-8" standalone="yes"?>
finally子句
JVM执行Java字节码时Q它有几U方式可以退Z个代码块Q花括号中间的语句)。其中之一Q就是简单的执行完其中所有的语句Q然后退Z码块。第二种QJVM可能会在代码块中间的M一处,遇到像breakQcontinueQreturn之类的语句,强制它蟩代码块。第三种QJVM可能会在执行q程中,出现了异常,然后它蟩转到匚w的catch子句Q或者没有找到相应的catch子句Q直接退出当前线E。由于单个代码块有如此多的潜在退出点Qexit pointQ,拥有一个简单的方式来表䏀无Z码块以什么方式退出,有些事情总能发生”是很值得的。然后就有了try-finally子句?nbsp; 阅读全文
]]>
异常处理
在程序运行时Q异常让你可以^滑的处理意外状况。ؓ了演CJVM处理异常的方式,考虑NitPickyMathc,它提供对整数q行加,减,乘,除以及取余的操作?br />
NitPickyMath提供的这些操作和Java语言?#8220;+”Q?#8220;-”Q?#8220;*”Q?#8220;/”?#8220;%”是一LQ除了NitPickyMath中的Ҏ在以下情况下会抛出检查型QcheckedQ异常:上溢出,下溢Z及被0除?做除数时QJVM会抛出ArithmeticException异常Q但是上溢出和下溢出不会引发M异常。NitPickyMath中抛出异常的Ҏ定义如下Q?/p>
NitPickyMathcM的remainder()Ҏ是一个抛出和捕获异常的简单方法?/p>
remainder()ҎQ只是简单的对当作参C递进来的2个整数进行取余操作。如果取余操作的除数?Q会引发ArithmeticException异常。remainder()Ҏ捕获q个异常Qƈ重新抛出DivideByZeroException异常?/p>
DivideByZeroException和ArithmeticException的区别是QDivideByZeroException是检查型QcheckedQ异常,而ArithmeticException是非查(uncheckedQ型异常。由于ArithmeticException是非查型异常Q一个方法就会抛出该异常,也不必在其throw子句中声明它。Q何Error或RuntimeException异常的子cd帔R是非查型异常。(ArithmeticException是RuntimeException的子cR)通过捕获ArithmeticException和抛出DivideByZeroExceptionQremainder()Ҏ它的调用者去处理除数?的可能性,要么捕获它,要么在其throw子句中声明DivideByZeroException异常。这是因为,像DivideByZeroExceptionq种在方法中抛出的检查型异常Q要么在Ҏ中捕P要么在其throw子句中声明,二者必选其一。而像ArithmeticExceptionq种非检查型异常Q就不需要去昑ּ捕获和声明?/p>
javac为remainder()Ҏ生成的字节码序列如下Q?/p>
remainder()Ҏ的字节码?个单独的部分。第一部分是该Ҏ的正常执行\径,q部分从W?行开始,到第3行结束。第二部分是从第4行开始,?2行结束的catch子句?/p>
d节码序列中的irem指o可能会抛出ArithmeticException异常。如果异常发生了QJVM通过在异常表中查扑配的异常Q它会知道要跌{到相应的异常处理的catch子句的字节码序列部分。每个捕获异常的ҎQ都跟类文g中与Ҏ字节码一起交付的异常表关联。每一个捕获异常的try块,都是异常表中的一行。每?条信息:开始行PfromQ和l束行号QtoQ,要蟩转的字节码序列行PtargetQ,被捕L异常cȝ帔R池烦引(typeQ。remainder()Ҏ的异常表如下所C:
FROM
|
TO
|
TARGET
|
TYPE
|
---|---|---|---|
0 | 4 | 4 | < Class java.lang.ArithmeticException > |
上面的异常表表明Q行??范围内,ArithmeticException被捕获。异常表中的“to”下面的结束行号始l比异常捕获的最大行号大1Q上表中Q结束行号ؓ4Q而异常捕L最大行h3。行??的字节码序列对应remainder()Ҏ中的try块?#8220;target”列中Q是??的字节码发生ArithmeticException异常时要跌{到的目标行号?/p>
如果Ҏ执行q程中生了异常QJVM会在异常表中查找匚w行。异常表中的匚w行要W合下面的条Ӟ当前pc寄存器的D在该行的表示范围之内Q[from, to)Q且产生的异常是该行所指定的异常类或其子类。JVM按从上到下的ơ序查找异常表。当扑ֈ了第一个匹配行QJVM把pc寄存器设为新的蟩转行P从此行l往下执行。如果找不到匚w行,JVM弹出当前栈Qƈ重新抛出同一个异常。当JVM弹出当前栈Ӟ它会l止当前Ҏ的执行,q回到调用该Ҏ的上一个方法那里。这Ӟ在上一个方法里Qƈ不会l箋正常的执行过E,而是抛出同样的异常,促JVM重新查找该方法的异常表?/p>
JavaE序员可以用throw语句抛出像remainder()Ҏ的catch子句中的异常QDivideByZeroException。下表列Z抛出异常的字节码Q?/p>
OPCODE
|
OPERAND(S)
|
DESCRIPTION
|
---|---|---|
athrow | (none) | pops Throwable object reference, throws the exception |
athrow指o把栈元素弹出,该元素必LThrowable的子cL其自w的对象引用Q而抛出的异常cd由栈弹出的对象引用所指明?/p>
本文译自Q?a target="_blank" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; outline: none; color: #21759b;">How the Java virtual machine handles exceptions
本文Q?/strong>码农合作C?/a> ?a style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; outline: none; color: #21759b;">JVM中的异常处理Q{载请注明?/p>
什么是JVMQؓ什么要有它Q?/strong>
JVMQJava虚拟机)是一个运行已~译JavaE序的抽象计机。之所以说?#8221;虚拟“的,是因为它Z“真正”的硬件^台和操作pȝQ一般以软g的Ş式实现。所有的JavaE序都ؓJVM而编译。因此,在特定^Cq行已编译JavaE序之前Q该q_的JVM必须先要被实现?/p>
JVM在Java的跨q_Ҏ中Qv着中间人的角色。它在已~译JavaE序与底层硬件^台和操作pȝ之间Q提供一个抽象层。JVM对Java的可UL性非常关键,因ؓQ已~译JavaE序q行在JVM之上Qƈ独立于底层JVM的具体实现?/p>
那么Q是什么导致JVM的短精悍?当被实现成Y件时QJMV很小巧。它被设计成q样Q是Z让它能够适用于尽可能多的地方Q比如机盒Q手机和个h电脑。JVM很精悍,是因为它的野心?#8221;无处不在Q?#8220;是它的战斗口受它惌无处不在Qƈ且JavaE序”一ơ编写,到处q行“的程度说明了它的成功?br />
Java字节?/strong>
JavaE序被编译成一U叫做字节码的东东。JVM执行Java字节码,所以字节码可以被认为是JVM的机器语a。Java~译器读取Java源文Ӟ把它译成Java字节码ƈ保存到类文gQ?class文gQ中。编译器会ؓ源码中的每一个类生成一个类文g?/p>
对JVM来说Q字节码就是指令序列。每条指令包含一个单字节的操作码和零个或多个操作数。操作码告诉JVM要执行的操作。如果JVM需要除操作码之外更多的信息L行一Ҏ作,那么Q需要的信息作ؓ操作敎ͼ紧跟在操作码之后?/p>
每个字节码都有一个助记符Q它可被当作JVM的汇~语a。例如,有个指o会让JVM?压到堆栈中。该指o的助记符是iconst_0Q字节码值是0×60。该指o没有操作数。另一个指令让E序的执行在内存中无条g向前向后跌{。这个指令需要一个操作数Q它是一个指明从当前内存地址开始的2字节无符号偏U量。通过把偏U量加到当前内存地址QJVM可以获得要蟩转的目标内存地址。该指o的助记符是gotoQ它的字节码值是0xa7?/p>
虚拟部分
JVM?#8220;虚拟g”可以分ؓ四个部分Q寄存器l,栈区Q垃圾收集堆和方法区。这些部分很抽象Q就像由它们l成的虚拟机一P但是它们必须在每个JVM的实CQ以某种形式存在?/p>
JVM中地址的是32位(4字节Q的Q因此,JVM可以处理4GBQ??2ơ方Q的内存。栈区,垃圾攉堆和Ҏ区处在这4GB内存中的某个地方Q至于它们的具体内存地址Q这取决于每个特定JVM的实现者?/p>
JVM中一个字QwordQ的长度?2位的。JVM中有数几个原始数据cdQbyteQ?位)QshortQ?6位)QintQ?2位)QlongQ?4位)QfloatQ?2位)QdoubleQ?4位)QcharQ?6位)。除了无W号Unicode字符char之外Q其?U数字类型都是有W号的。这些类型可以方便的映射到JavaE序员可用的数据cd。另一个原始类型是对象句柄Q它是一个指向堆中对象的32位地址?/p>
׃包含字节码,ҎZ字节边界寚w。栈和垃圾收集堆以字Q?2位)边界寚w1?/p>
寄存器:我少我自?/strong>
JVM?个程序计数器QcounterQ和3个管理栈的寄存器QregisterQ。它只有很少的寄存器Q是因ؓJVM字节码指令主要操作栈区。这U面向栈的设计,使得JVM指o集和JVM实现很小巧?/p>
JVM使用E序计数器(也叫pc寄存器)Q跟t当前执行指令的内存位置。另?个寄存器Qoptop寄存器,frame寄存器和vars寄存器)指向当前执行Ҏ栈上不同的部位。执行方法的栈持有特定Ҏ调用的状态(本地变量Q即时计结果等Q?/p>
Ҏ区和E序计数?/strong>
Ҏ区是字节码呆的地斏V程序计数器跟踪执行U程。当前字节码指o执行后,E序计数器会包含下一条执行指令的地址Q一条指令执行之后,JVM把程序计数器讄为紧跟上一条指令的指o地址Q除非上一条指令具体指明一ơ蟩转?/p>
Java栈和相关寄存?/strong>
Java栈用来保存字节码指o的参数和执行l果Q给Ҏ传递参数和q回l果Q保存每个方法调用的状态。方法调用的状态被UCؓ调用栈。var寄存器,frame寄存器和optop寄存器指向当前栈帧的不同部位?/p>
Java栈?个区Q本地变量,执行环境和操作数栈。本地变量区Q包含当前方法调用中使用的所有本地变量。它由vars寄存器指向。执行环境区用来l护栈区本n的操作。它被frame寄存器指向。操作数区用来作为字码指令的工作区。正是在q里Q存攄字节码指令的参数和其q回l果。操作数栈区的顶部被optop寄存器指向?/p>
执行环境通常夹在本地变量和操作数栈中间。当前执行方法的操作数栈L在栈区的最上面Q所以optop寄存器L指向整个Java栈的剙?/p>
垃圾攉?/strong>
堆是Java对象生存的地斏VQ何时候,你用new操作W分配的内存Q都来自堆中。Java语言不允怽直接释放分配的内存。运行时环境会跟t堆上每个对象的引用Q自动释N些不被引用的对象所占据的内存,q个q程被称为垃圾收集?/p>
参?/strong>
本文译自Q?a style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; outline: none; color: #9f9f9f;">The lean, mean, virtual machine
原创文章Q{载请注明Q?/strong> 转蝲?a style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; outline: none; color: #9f9f9f;">LetsCoding.cn
本文链接地址: 短小_悍的虚拟机QJVM基本l构和功能介l?/span>
{略模式通过装一l相关算法,为Client提供q行时的灉|性。Client可以在运行时Q选择M法Q而不改变使用法的Context。一些流行的{略模式的例子是写那些用算法的代码Q例如加密算法、压~算法、排序算法。另一斚wQ状态模式允许对象,在不同的状态拥有不同的行ؓ。因为现实世界中的对象通常都是有状态的Q所以它们在不同状态,行ؓ也不一栗例如,VMQ自动售货机Q只在hasCoin状态才l你吐商品;你不投币Q它是不会吐的。现在你可以清楚的看出它们的不同之处了:它们的意图是不同的。状态模式帮助对象管理状态,而策略模式允许Client选择不同的行为?/span>
另一个不那么Ҏ能看出来的区别是Q是谁促使了行ؓ的改变。策略模式中Q是Client提供了不同的{略lContextQ状态模式中Q状态{UȝContext或State自己理。另外,如果你在State中管理状态{U,那么它必L有Context的引用。例如,在VM的例子中QState对象需要调用VM的setState()ҎL变它的状态。另一斚wQStrategy从不持有Context的引用,是Client把所选择的Strategy传递给Context。由于状态模式和{略模式的区别,是流行的Java设计原则c面试题之一Q我们将会在本文探讨在Java中,状态模式和{略模式的异同,q可以加׃对它们的理解?/span>
怼之处
如果你看看状态模式和{略模式的UML图,׃发现它们的结构非常相伹{用State对象改变自己行ؓ的对象被UCؓContext对象Q相似的Q用Strategy对象改变自己行ؓ的对象叫Context对象。记住,Client和Context打交道。在状态模式中QContext把方法调用委托给当前的状态对象,而在{略模式中,Context使用的Strategy对象Q是被当做参C递过来的Q或在Context对象被创建时p提供的?/span>
q是专ؓl典的VM问题而设计的状态模式UMLcd。你可以看出QVM的状态是个接口,它有表示不同状态的具体实现。每一个状态都持有Context的引用,用它来管理由Context触发的行为导致的状态{UR?/span>
q是专ؓ实现排序功能而设计的{略模式UMLcd。因为存在很多排序算法,该模式让Client在排序时选择适当的算法。事实上QJava的集合框架就使用q个模式Q实C用来排序的Collections.sort()Ҏ。不同的是,它不允许Client选择排序法Q而是让它传递Comparator或Comparable接口的实例来指定比较{略?/span>
让我们来看看它们之间更多的相g处:
不同之处
现在我们知道Q状态模式和{略模式的结构是怼的,但它们的意图不同。让我们重温一下它们的主要不同之处Q?/span>
本文译自Q?/span>Difference between State and Strategy Design Pattern in Java
原创文章Q{载请注明Q?/strong> 转蝲?/span>LetsCoding.cn
本文链接地址: Java中,状态模式和{略模式的区?/span>