alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (TryStatement.java)

This example Java source code file (TryStatement.java) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

assembler, catchstatement, checkcontext, classdeclaration, classdefinition, codecontext, context, enumeration, hashtable, statement, trydata, trystatement, type, util, vset

The TryStatement.java Java example source code

/*
 * Copyright (c) 1994, 2003, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package sun.tools.tree;

import sun.tools.java.*;
import sun.tools.asm.Assembler;
import sun.tools.asm.Label;
import sun.tools.asm.TryData;
import sun.tools.asm.CatchData;
import java.io.PrintStream;
import java.util.Enumeration;
import java.util.Hashtable;

/**
 * WARNING: The contents of this source file are not part of any
 * supported API.  Code that depends on them does so at its own risk:
 * they are subject to change or removal without notice.
 */
public
class TryStatement extends Statement {
    Statement body;
    Statement args[];
    long arrayCloneWhere;       // private note posted from MethodExpression

    /**
     * Constructor
     */
    public TryStatement(long where, Statement body, Statement args[]) {
        super(TRY, where);
        this.body = body;
        this.args = args;
    }

    /**
     * Check statement
     */
    Vset check(Environment env, Context ctx, Vset vset, Hashtable exp) {
        checkLabel(env, ctx);
        try {
            vset = reach(env, vset);
            Hashtable newexp = new Hashtable();
            CheckContext newctx =  new CheckContext(ctx, this);

            // Check 'try' block.  A variable is DA (DU) before the try
            // block if it is DA (DU) before the try statement.
            Vset vs = body.check(env, newctx, vset.copy(), newexp);

            // A variable is DA before a catch block if it is DA before the
            // try statement.  A variable is DU before a catch block if it
            // is DU after the try block and before any 'break', 'continue',
            // 'throw', or 'return' contained therein. That is, the variable
            // is DU upon entry to the try-statement and is not assigned to
            // anywhere within the try block.
            Vset cvs = Vset.firstDAandSecondDU(vset, vs.copy().join(newctx.vsTryExit));

            for (int i = 0 ; i < args.length ; i++) {
                // A variable is DA (DU) after a try statement if
                // it is DA (DU) after every catch block.
                vs = vs.join(args[i].check(env, newctx, cvs.copy(), exp));
            }

            // Check that catch statements are actually reached
            for (int i = 1 ; i < args.length ; i++) {
                CatchStatement cs = (CatchStatement)args[i];
                if (cs.field == null) {
                    continue;
                }
                Type type = cs.field.getType();
                ClassDefinition def = env.getClassDefinition(type);

                for (int j = 0 ; j < i ; j++) {
                    CatchStatement cs2 = (CatchStatement)args[j];
                    if (cs2.field == null) {
                        continue;
                    }
                    Type t = cs2.field.getType();
                    ClassDeclaration c = env.getClassDeclaration(t);
                    if (def.subClassOf(env, c)) {
                        env.error(args[i].where, "catch.not.reached");
                        break;
                    }
                }
            }

            ClassDeclaration ignore1 = env.getClassDeclaration(idJavaLangError);
            ClassDeclaration ignore2 = env.getClassDeclaration(idJavaLangRuntimeException);

            // Make sure the exception is actually throw in that part of the code
            for (int i = 0 ; i < args.length ; i++) {
                CatchStatement cs = (CatchStatement)args[i];
                if (cs.field == null) {
                    continue;
                }
                Type type = cs.field.getType();
                if (!type.isType(TC_CLASS)) {
                    // CatchStatement.checkValue() will have already printed
                    // an error message
                    continue;
                }

                ClassDefinition def = env.getClassDefinition(type);

                // Anyone can throw these!
                if (def.subClassOf(env, ignore1) || def.superClassOf(env, ignore1) ||
                    def.subClassOf(env, ignore2) || def.superClassOf(env, ignore2)) {
                    continue;
                }

                // Make sure the exception is actually throw in that part of the code
                boolean ok = false;
                for (Enumeration e = newexp.keys() ; e.hasMoreElements() ; ) {
                    ClassDeclaration c = (ClassDeclaration)e.nextElement();
                    if (def.superClassOf(env, c) || def.subClassOf(env, c)) {
                        ok = true;
                        break;
                    }
                }
                if (!ok && arrayCloneWhere != 0
                    && def.getName().toString().equals("java.lang.CloneNotSupportedException")) {
                    env.error(arrayCloneWhere, "warn.array.clone.supported", def.getName());
                }

                if (!ok) {
                    env.error(cs.where, "catch.not.thrown", def.getName());
                }
            }

            // Only carry over exceptions that are not caught
            for (Enumeration e = newexp.keys() ; e.hasMoreElements() ; ) {
                ClassDeclaration c = (ClassDeclaration)e.nextElement();
                ClassDefinition def = c.getClassDefinition(env);
                boolean add = true;
                for (int i = 0 ; i < args.length ; i++) {
                    CatchStatement cs = (CatchStatement)args[i];
                    if (cs.field == null) {
                        continue;
                    }
                    Type type = cs.field.getType();
                    if (type.isType(TC_ERROR))
                        continue;
                    if (def.subClassOf(env, env.getClassDeclaration(type))) {
                        add = false;
                        break;
                    }
                }
                if (add) {
                    exp.put(c, newexp.get(c));
                }
            }
            // A variable is DA (DU) after a try statement if it is DA (DU)
            // after the try block and after every catch block. These variables
            // are represented by 'vs'.  If the try statement is labelled, we
            // may also exit from it (including from within a catch block) via
            // a break statement.
            // If there is a finally block, the Vset returned here is further
            // adjusted. Note that this 'TryStatement' node will be a child of
            // a 'FinallyStatement' node in that case.
            return ctx.removeAdditionalVars(vs.join(newctx.vsBreak));
        } catch (ClassNotFound e) {
            env.error(where, "class.not.found", e.name, opNames[op]);
            return vset;
        }
    }

    /**
     * Inline
     */
    public Statement inline(Environment env, Context ctx) {
        if (body != null) {
            body = body.inline(env, new Context(ctx, this));
        }
        if (body == null) {
            return null;
        }
        for (int i = 0 ; i < args.length ; i++) {
            if (args[i] != null) {
                args[i] = args[i].inline(env, new Context(ctx, this));
            }
        }
        return (args.length == 0) ? eliminate(env, body) : this;
    }

    /**
     * Create a copy of the statement for method inlining
     */
    public Statement copyInline(Context ctx, boolean valNeeded) {
        TryStatement s = (TryStatement)clone();
        if (body != null) {
            s.body = body.copyInline(ctx, valNeeded);
        }
        s.args = new Statement[args.length];
        for (int i = 0 ; i < args.length ; i++) {
            if (args[i] != null) {
                s.args[i] = args[i].copyInline(ctx, valNeeded);
            }
        }
        return s;
    }

    /**
     * Compute cost of inlining this statement
     */
    public int costInline(int thresh, Environment env, Context ctx){

        // Don't inline methods containing try statements.
        // If the try statement is being inlined in order to
        // inline a method that returns a value which is
        // a subexpression of an expression involving the
        // operand stack, then the early operands may get lost.
        // This shows up as a verifier error.  For example,
        // in the following:
        //
        //    public static int test() {
        //       try { return 2; } catch (Exception e)  { return 0; }
        //    }
        //
        //    System.out.println(test());
        //
        // an inlined call to test() might look like this:
        //
        //     0 getstatic <Field java.io.PrintStream out>
        //     3 iconst_2
        //     4 goto 9
        //     7 pop
        //     8 iconst_0
        //     9 invokevirtual <Method void println(int)>
        //    12 return
        //  Exception table:
        //     from   to  target type
        //       3     7     7   <Class java.lang.Exception>
        //
        // This fails to verify because the operand stored
        // for System.out gets axed at an exception, leading to
        // an inconsistent stack depth at pc=7.
        //
        // Note that although all code must be able to be inlined
        // to implement initializers, this problem doesn't come up,
        // as try statements themselves can never be expressions.
        // It suffices here to make sure they are never inlined as part
        // of optimization.

        return thresh;
    }

    /**
     * Code
     */
    public void code(Environment env, Context ctx, Assembler asm) {
        CodeContext newctx = new CodeContext(ctx, this);

        TryData td = new TryData();
        for (int i = 0 ; i < args.length ; i++) {
            Type t = ((CatchStatement)args[i]).field.getType();
            if (t.isType(TC_CLASS)) {
                td.add(env.getClassDeclaration(t));
            } else {
                td.add(t);
            }
        }
        asm.add(where, opc_try, td);
        if (body != null) {
            body.code(env, newctx, asm);
        }

        asm.add(td.getEndLabel());
        asm.add(where, opc_goto, newctx.breakLabel);

        for (int i = 0 ; i < args.length ; i++) {
            CatchData cd = td.getCatch(i);
            asm.add(cd.getLabel());
            args[i].code(env, newctx, asm);
            asm.add(where, opc_goto, newctx.breakLabel);
        }

        asm.add(newctx.breakLabel);
    }

    /**
     * Print
     */
    public void print(PrintStream out, int indent) {
        super.print(out, indent);
        out.print("try ");
        if (body != null) {
            body.print(out, indent);
        } else {
            out.print("<empty>");
        }
        for (int i = 0 ; i < args.length ; i++) {
            out.print(" ");
            args[i].print(out, indent);
        }
    }
}

Other Java examples (source code examples)

Here is a short list of links related to this Java TryStatement.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.