参考:

(1)https://docs.oracle.com/javase/specs/jls/se7/html/jls-16.html

(2)https://docs.oracle.com/javase/specs/jls/se7/html/jls-14.html#jls-14.1 后面的Unreachable Statements部分

This pass implements dataflow analysis for Java programs.

Liveness analysis checks that every statement is reachable.

Exception analysis ensures that every checked exception that is thrown is declared or caught.

Definite(一定的、确定的) assignment analysis ensures that each variable is assigned when used.

如上指出了要做的三项工作,分别是Liveness analysis、Exception analysis与DA/DU

eg:

任何局部变量在使用前要进行初始化,包括基本类型,如下将报错:

int i;
if(i==2){ // 报错,局部变量i未初始化

}

Definite unassignment analysis ensures that no final variable is assigned more than once(不止一次).

eg:

final int i;
i = 1;
i = 22; // The final local variable i may already have been assigned

  

The JLS has a number of problems in the specification of these flow analysis problems.This implementation attempts to address those issues.

First, there is no accommodation for a finally clause that cannot complete normally.

For liveness analysis, an intervening finally clause can cause a break, continue, or return not to reach its target.

For exception analysis, an intervening finally clause can cause any exception to be "caught".

eg:

什么是intervening finally,就比如finally中有return 、continue等有控制流程转移的语句。

for(int i=0;i<2;i++){
			try{
				System.out.println("a");
				break;
			}catch(Exception ex){

			}finally{ // finally block does not complete normally
				System.out.println("b");
				continue;
			}
}  

输出为:a b a b

@SuppressWarnings("finally")
private boolean isReturnWithinFinally() {
		try {
			if (true)
				throw new RuntimeException();
		} finally {
			return true; // This hides the exception
		}
} 

所以这是一个Finally block may not complete normally 的问题。

A 'finally' block that runs because an exception has been thrown, and that does not complete normally, causes the exception to disappear silently.

finally block that does not complete normally suppresses any exceptions that may have been thrown in the corresponding try block. This can happen if the finally block contains any return or throw statements, or if it contains any break or continue statements whose jump target lies outside of the finally block.

To avoid suppressing exceptions that are thrown in a try block, design the code so that the corresponding finally block always completes normally. Remove any of the following statements that may cause it to terminate abnormally:

  • return
  • throw
  • break
  • continue

用如下图总结一下:

参考:

(1)https://help.semmle.com/wiki/display/JAVA/Finally+block+may+not+complete+normally

(2)http://etutorials.org/cert/java+certification/Chapter+5.+Control+Flow+Exception+Handling+and+Assertions/5.7+Exception+Handling+try+catch+and+finally/

For DA/DU analysis, the finally clause can prevent a transfer of control(控制权的转移) from propagating(传播) DA/DU state to the target. In addition(另外), code in the finally clause can affect the DA/DU status of variables.

For try statements, we introduce the idea of a variable being definitely unassigned "everywhere" in a block.
A variable V is "unassigned everywhere" in a block iff(if and only if) it is unassigned at the beginning of the block and there is no reachable assignment to V in the block.

An assignment V=e is reachable iff V is not DA after e. Then we can say that V is DU at the beginning of the catch block iff V is DU everywhere in the try block. 如上的变量e说的可能是catch块的Exception中的变量e

Similarly,V is DU at the beginning of the finally block iff V is DU everywhere in the try block and in every catch block.

Specifically, the following bullet is added to 16.2.2

V is unassigned everywhere in a block if it is unassigned before the block and there is no reachable assignment to V within the block.

In 16.2.15, the third bullet (and all of its sub-bullets) for all try blocks is changed to

V is definitely unassigned before a catch block iff V is definitely unassigned everywhere in the try block.

The last bullet (and all of its sub-bullets) for try blocks that have a finally block is changed to

V is definitely unassigned before the finally block iff V is definitely unassigned everywhere in the try block and everywhere in each catch block of the try statement.

In addition,

V is definitely assigned at the end of a constructor iff V is definitely assigned after the block that is the body of the constructor and V is definitely assigned at every return that can return from the constructor.

In addition, each continue statement with the loop as its target is treated as a jump to the end of the loop body,and "intervening" finally clauses are treated as follows:

V is DA "due to(归因于) the continue" iff V is DA before the continue statement or V is DA at the end of any intervening finally block.

V is DU "due to the continue" iff any intervening finally cannot complete normally or V is DU at the end of every intervening finally block. This "due to the continue" concept is then used in the spec for the loops.

Similarly, break statements must consider intervening finally blocks.

For liveness analysis, a break statement for which any intervening finally cannot complete normally is not considered to cause the target statement to be
able to complete normally. Then we say V is DA "due to the break" iff V is DA before the break or V is DA
at the end of any intervening finally block. V is DU "due to the break" iff any intervening finally cannot complete normally
or V is DU at the break and at the end of every intervening finally block. (I suspect this latter condition can be simplified.)
This "due to the break" is then used in the spec for all statements that can be "broken".

The return statement is treated similarly. V is DA "due to a return statement" iff V is DA before the return statement
or V is DA at the end of any intervening finally block. Note that we don't have to worry about the return expression because this concept is only used for construcrors.

There is no spec in JLS2 for when a variable is definitely assigned at the end of a constructor, which is needed for
final fields (8.3.1.2). We implement the rule that V is DA at the end of the constructor iff it is DA and the end of
the body of the constructor and V is DA "due to" every return of the constructor.

Intervening finally blocks similarly affect exception analysis. An intervening finally that cannot complete normally allows us to ignore an otherwise uncaught exception.

To implement the semantics of intervening finally clauses, all nonlocal transfers (break, continue, return, throw,
method call that can throw a checked exception, and a constructor invocation that can thrown a checked exception)
are recorded in a queue, and removed from the queue when we complete processing the target of the nonlocal transfer.
This allows us to modify the queue in accordance with the above rules when we encounter a finally clause.
The only exception to this [no pun intended 没有双关] is that checked exceptions that are known to be caught or declared
to be caught in the enclosing method are not recorded in the queue, but instead are recorded in a global variable
"Set thrown" that records the type of all exceptions that can be thrown.

Other minor issues the treatment of members of other classes (always considered DA except that within an anonymous class constructor, where DA status from the enclosing scope is preserved),

treatment of the case expression (V is DA before the case expression iff V is DA after the switch expression), treatment of variables declared in a
switch block (the implied DA/DU status after the switch expression is DU and not DA for variables defined in a switch block),

the treatment of boolean ?: expressions (The JLS rules only handle b and c non-boolean; the new rule is that
if b and c are boolean valued, then V is (un)assigned after a?b:c when true/false iff V is (un)assigned after b
when true/false and V is (un)assigned after c when true/false).

There is the remaining question of what syntactic forms constitute(组成) a reference to a variable. It is conventional to
allow this.x on the left-hand-side to initialize a final instance field named x, yet this.x isn't considered a "use" when appearing on a right-hand-side in most implementations.

Should parentheses affect what is considered a variable reference?(括号会影响被视为变量引用的内容)The simplest rule would be to allow unqualified forms only, parentheses optional, and phase out support for assigning to a final field via this.x.

参考:

(1)https://docs.oracle.com/javase/specs/jls/se7/html/jls-16.html

Flow类注释解读的更多相关文章

  1. VAssistX的VA Snippet Editor的类注释和函数注释

    title:类注释shortcut:=== /******************************************************** [DateTime]:$YEAR$.$M ...

  2. IDEA(添加类注释以及方法注释)

    添加类注释: File---Setting----Editor----Code Style-----File and    Code  Templates--------Class #if (${PA ...

  3. PhpStorm 头部注释、类注释和函数注释的设置

    *设置位置:"Settings"->"file templates"; 如下图,设置头部注释.类注释以及函数注释,时间.用户名.文件名称等随机改变的属性, ...

  4. 超详细设置Idea类注释模板和方法注释模板

    网上找了一下,没有很详细且正确介绍Idea配置注释模板的,于是结合多篇文章自己琢磨整理出如下. 设置类注释模板 1.选择File–>Settings–>Editor–>File an ...

  5. idea生成类注释和方法注释的正确方法

    系统:Mac OS idea版本:2017.3.1 ---------------- 生成类注释 打开Preferences Editor -> File and Code Templates ...

  6. Idea设置类注释模板

    1.选择File–>Settings–>Editor–>File and Code Templates–>Includes–>File Header. 在Descript ...

  7. IntelliJ Idea注释模板--类注释、方法注释

    刚从Eclipse切换到IntelliJ Idea,之前使用eclipse时用到了注释模板,包括类注释和方法注释,现在分别讲一下在Intellij Idea中如何进行配置,作为备忘 一. 类注释模板配 ...

  8. Hibernate---数据操作示例BY实体类注释

    通过实体的映射文件创建表的示例,除了基本jar包外,还需要jar包如下 ejb3-persistence.jar.hibernate-annotations.jar这两个包均在hibernate-an ...

  9. IntelliJ IDEA 添加类注释模板

    效果展示 /** * Created with IntelliJ IDEA * USER:jacun * CLASSNAME: HalloWorldController * DATE: 2019/1/ ...

随机推荐

  1. 记录:Web相关政策之备案号、视频播放

    (一)备案号链接: 服务器在国内的网站受工信部监管,并受其颁布的<管理办法>约束.根据<互联网信息服务管理办法>及<非经营性互联网信息服务备案管理办法>的法律法规, ...

  2. 对于java的命名规范(标识符)

    java的命名规范基本都需要使用标识符来命名的: 标识符的介绍: 标识符作用: 给变量起名字的用的. 标识符的组成: 1.Unicode编码:包含大.小写字母,数字,汉字(不建议使用).  2.美元符 ...

  3. (并查集)小希的迷宫 --HDU -- 1272

    链接: http://acm.hdu.edu.cn/showproblem.php?pid=1272 http://acm.hust.edu.cn/vjudge/contest/view.action ...

  4. Trystrtofloat

    TryStrToFloat为 ‘+1’和‘-1’和 ‘.1’是可以装换成功的

  5. Android 了解1G 2G 3G 知识

    了解1G 2G 3G 相关知识,对网络通讯制式进行了解即可 1.这种网络通讯制式是一步一步发展起来的,由最开始的1G(最典型的手机,例如:大哥大,1G这种制式只能语音通话). 2.后来出现的2G,2G ...

  6. oracle只导出触发器

    只要触发器,其他都不要 方法1:plsql develop调用exp:tools->export object—>trigger 方法2:select dbms_metadata.get_ ...

  7. net生成图片验证码--转自Lisliefor

    目前,机器识别验证码已经相当强大了,比较常见的避免被机器识别的方法,就是将验证码的字符串连到一起,这样就加大的识别的难度,毕竟机器没有人工智能.我找了很多的.net生成图片验证码的例子,后来经过一些修 ...

  8. MVC下使用Areas

    (一) 为什么要分离 MVC项目各部分职责比较清晰,相比较ASP.NET Webform而言,MVC项目的业务逻辑和页面展现较好地分离开来,这样的做法有许多优点,比如可测试,易扩展等等.但是在实际的开 ...

  9. oracle12c不能进入到http://localhost:1158/em的解决办法

    oracle12c的em经过精简,比11g小 很多,登陆方式也发生了变化,原来的https://localhost:1158/em或者https://localhost:1158/em登陆总是会遇到问 ...

  10. Access 2010 应用基础 单元三:SQL查询

    导语:Access查询中拉差距的部分 简单查询 [是基于单个表的查询] 无条件从数据表中选择部分字段 Select 字段列表 from 数据表 无条件从数据表中选择全部字段 Select 字段列表 f ...