protected ReferenceType mergeReferenceTypes ( ReferenceType aRef , ReferenceType bRef ) throws DataflowAnalysisException { if ( aRef . equals ( bRef ) ) { return aRef ; } byte aType = aRef . getType ( ) ; byte bType = bRef . getType ( ) ; try { // Special case: ExceptionObjectTypes. // We want to preserve the ExceptionSets associated, // in order to track the exact set of exceptions if ( isObjectType ( aType ) && isObjectType ( bType ) && ( ( aType == T_EXCEPTION || isThrowable ( aRef ) ) && ( bType == T_EXCEPTION || isThrowable ( bRef ) ) ) ) { ExceptionSet union = exceptionSetFactory . createExceptionSet ( ) ; if ( aType == Const . T_OBJECT && "Ljava/lang/Throwable;" . equals ( aRef . getSignature ( ) ) ) { return aRef ; } if ( bType == Const . T_OBJECT && "Ljava/lang/Throwable;" . equals ( bRef . getSignature ( ) ) ) { return bRef ; } updateExceptionSet ( union , ( ObjectType ) aRef ) ; updateExceptionSet ( union , ( ObjectType ) bRef ) ; Type t = ExceptionObjectType . fromExceptionSet ( union ) ; if ( t instanceof ReferenceType ) { return ( ReferenceType ) t ; } } if ( aRef instanceof GenericObjectType && bRef instanceof GenericObjectType && aRef . getSignature ( ) . equals ( bRef . getSignature ( ) ) ) { GenericObjectType aG = ( GenericObjectType ) aRef ; GenericObjectType bG = ( GenericObjectType ) bRef ; if ( aG . getTypeCategory ( ) == bG . getTypeCategory ( ) ) { switch ( aG . getTypeCategory ( ) ) { case PARAMETERIZED : List < ? extends ReferenceType > aP = aG . getParameters ( ) ; List < ? extends ReferenceType > bP = bG . getParameters ( ) ; assert aP != null ; assert bP != null ; if ( aP . size ( ) != bP . size ( ) ) { break ; } ArrayList < ReferenceType > result = new ArrayList <> ( aP . size ( ) ) ; for ( int i = 0 ; i < aP . size ( ) ; i ++ ) { result . add ( mergeReferenceTypes ( aP . get ( i ) , bP . get ( i ) ) ) ; } GenericObjectType rOT = GenericUtilities . getType ( aG . getClassName ( ) , result ) ; return rOT ; } } } if ( aRef instanceof GenericObjectType ) { aRef = ( ( GenericObjectType ) aRef ) . getObjectType ( ) ; } if ( bRef instanceof GenericObjectType ) { bRef = ( ( GenericObjectType ) bRef ) . getObjectType ( ) ; } if ( Subtypes2 . ENABLE_SUBTYPES2_FOR_COMMON_SUPERCLASS_QUERIES ) { return AnalysisContext . currentAnalysisContext ( ) . getSubtypes2 ( ) . getFirstCommonSuperclass ( aRef , bRef ) ; } else { return aRef . getFirstCommonSuperclass ( bRef ) ; } } catch ( ClassNotFoundException e ) { lookupFailureCallback . reportMissingClass ( e ) ; return Type . OBJECT ; } }
Default implementation of merging reference types . This just returns the first common superclass which is compliant with the JVM Spec . Subclasses may override this method in order to implement extended type rules .