private ExceptionSet computeEdgeExceptionSet ( Edge edge , ExceptionSet thrownExceptionSet ) { if ( thrownExceptionSet . isEmpty ( ) ) { return thrownExceptionSet ; } ExceptionSet result = exceptionSetFactory . createExceptionSet ( ) ; if ( edge . getType ( ) == UNHANDLED_EXCEPTION_EDGE ) { // The unhandled exception edge always comes // after all of the handled exception edges. result . addAll ( thrownExceptionSet ) ; thrownExceptionSet . clear ( ) ; return result ; } BasicBlock handlerBlock = edge . getTarget ( ) ; CodeExceptionGen handler = handlerBlock . getExceptionGen ( ) ; ObjectType catchType = handler . getCatchType ( ) ; if ( Hierarchy . isUniversalExceptionHandler ( catchType ) ) { result . addAll ( thrownExceptionSet ) ; thrownExceptionSet . clear ( ) ; } else { // Go through the set of thrown exceptions. // Any that will DEFINITELY be caught be this handler, remove. // Any that MIGHT be caught, but won't definitely be caught, // remain. for ( ExceptionSet . ThrownExceptionIterator i = thrownExceptionSet . iterator ( ) ; i . hasNext ( ) ; ) { // ThrownException thrownException = i.next(); ObjectType thrownType = i . next ( ) ; boolean explicit = i . isExplicit ( ) ; if ( DEBUG ) { System . out . println ( "\texception type " + thrownType + ", catch type " + catchType ) ; } try { if ( Hierarchy . isSubtype ( thrownType , catchType ) ) { // Exception can be thrown along this edge result . add ( thrownType , explicit ) ; // And it will definitely be caught i . remove ( ) ; if ( DEBUG ) { System . out . println ( "\tException is subtype of catch type: " + "will definitely catch" ) ; } } else if ( Hierarchy . isSubtype ( catchType , thrownType ) ) { // Exception possibly thrown along this edge result . add ( thrownType , explicit ) ; if ( DEBUG ) { System . out . println ( "\tException is supertype of catch type: " + "might catch" ) ; } } } catch ( ClassNotFoundException e ) { // As a special case, if a class hierarchy lookup // fails, then we will conservatively assume that the // exception in question CAN, but WON'T NECESSARILY // be caught by the handler. AnalysisContext . reportMissingClass ( e ) ; result . add ( thrownType , explicit ) ; } } } return result ; }
Based on the set of exceptions that can be thrown from the source basic block compute the set of exceptions that can propagate along given exception edge . This method should be called for each outgoing exception edge in sequence so the caught exceptions can be removed from the thrown exception set as needed .