1

I'm trying to implement an intra-procedural analysis that computes, for each method, the set of exceptions that method may throw, including runtime exceptions that are explicitly thrown by means of a throw statement.

So far, I'm completely lost on how to start it with SOOT. Anyone can give me a first hint?

EijiAdachi
  • 441
  • 1
  • 3
  • 15
  • 1
    Just to be clear, you're trying to explicitly enumerate every possible runtime class of exception that might be thrown, including `RuntimeException`s thrown from called methods whose source may not be available? – chrylis -cautiouslyoptimistic- Aug 20 '13 at 02:13
  • I want to enumerate all exceptions: both checked and unchecked. More specifically, I want to enumerate precisely which exceptions are actually being raised, since a method may declare a more generic checked exception in its interface. Regarding the source code, there will be both cases: source case available, and only .class available. – EijiAdachi Aug 20 '13 at 02:17
  • 3
    But you'll always have at least the `.class` file of all actual implementing classes? Your system doesn't allow any `interface` implementations that are provided at runtime, such as through SPI? – chrylis -cautiouslyoptimistic- Aug 20 '13 at 02:19
  • (1) Yes, I'll always have at least .class. In fact, in almost every case I will have the source code available. (2) No – EijiAdachi Aug 20 '13 at 02:22
  • Although I've supplied an answer based on the stated requirements, I think it might be useful to explain why you need this. There may be an alternative, simpler solution to the underlying problem. – Patricia Shanahan Aug 20 '13 at 15:56

2 Answers2

1

You should look at implementations of ThrowsAnalysis. The analyses can be parameterized to make different assumptions about which statement can throw which exceptions. This analysis is intra-procedural, however, i.e., will have to make coarse assumptions about method calls. If you want to model method calls precisely then I recommend crafting an inter-procedural analysis with Heros.

Cheers, Eric

Eric
  • 1,343
  • 1
  • 11
  • 19
-1
  1. Index the classes and interfaces in your body of source and .class files, according to what they extend or implement. If A extends B which extends C which implements D, A should appear in the set of classes for all of B, C, and D.
  2. Starting from each method, initializer, static initializer block etc., find each constructor or method it might call. Create a set of called methods that includes the corresponding method in each subclass. If you call D's get(int) method you must include the corresponding methods in A, B, and C. You can find them using the index from Step 1.
  3. Starting from a method of interest, such as the main method or methods, form the list of all methods and constructors that might be called directly or indirectly. In effect, "indirectly calls" is the transitive closure of the relation build in step 2.
  4. Examine each possibly called method or constructor in the result of step 3. For each throw statement, report the type of the operand.

I will be very, very surprised if there is a benefit from this that justifies the cost.

Here's one example of a problem area. If you use the HashMap get() method, you use the Object equals() and hashCode() methods. Every class directly or indirectly extends Object, so the argument type for any throw statement in any equals() or hashCode() method is on the list.

Patricia Shanahan
  • 25,849
  • 4
  • 38
  • 75
  • In step 4, you meant throws clause (foo throws IOException) or throw statement (throw new Exception)? – EijiAdachi Aug 20 '13 at 02:42
  • @EijiAdachi "throw statement" - I've edited in the correction. However, remember the operand does not have to be a newly constructed object - it may be an existing exception, or one obtained by some method call. – Patricia Shanahan Aug 20 '13 at 02:49