Analysis of Exception Handling Patterns in Java Projects
Transcription
Analysis of Exception Handling Patterns in Java Projects
Analysis of Exception Handling Patterns in Java Projects: An Empirical Study Suman Nakshatri, Maithri Hegde, Sahithi Thandra David R. Cheriton School of Computer Science University of Waterloo Ontario, Canada {sdnaksha, m2hegde, sthandra}@uwaterloo.ca ABSTRACT Exception handling is a powerful tool provided by many programming languages to help developers deal with unforeseen conditions. Java is one of the few programming languages to enforce an additional compilation check on certain subclasses of the Exception class through Checked Exceptions. This enforcement has made the writing of exception handling code very common. Almost all the existing IDEs today give the suggestions and even generate the try-catch code automatically to assist the developers. This motivated us to study the habits of developers in general. As part of this study, empirical data was extracted from software projects developed in Java. The intent is to explore how developers respond to checked exceptions and identify common patterns used by them to deal with exceptions, checked or otherwise. Bloch’s book - “E↵ective Java” [1] was used as reference for best practices in exception handling - these recommendations were compared against results from the empirical data. Also, results of GitHub and SourceForge projects are compared for their similarities and di↵erences. Results of this study indicate that most programmers ignore checked exceptions and leave them unnoticed. Additionally, it is observed that classes higher in the exception class hierarchy are more frequently used as compared to specific exception subclasses. The paper also describes a potential solution to handling exceptions compiled from Bloch’s book and Bruce’s blog on exception handling. This explains the usage of custom exceptions and how they can lead to cleaner and scalable code. CCS Concepts •Software and its engineering ! Error handling and recovery; Keywords Java Exception Handling; Github; Best Practices; Boa Permission to make digital or hard copies of all or part of this work for personal or classroom use is granted without fee provided that copies are not made or distributed for profit or commercial advantage and that copies bear this notice and the full citation on the first page. Copyrights for components of this work owned by others than ACM must be honored. Abstracting with credit is permitted. To copy otherwise, or republish, to post on servers or to redistribute to lists, requires prior specific permission and/or a fee. Request permissions from permissions@acm.org. MSR’ 16, 14-15 May 2016, Austin, TX, USA c 2016 ACM. ISBN 123-4567-24-567/08/06. . . $15.00 DOI: 10.475/123 4 Table 1: Dataset Statistics for GitHub Total projects 7,830,023 Number of Java projects 554,864 Methods with atleast one catch block 10,862,172 Total number of Catch blocks 16,172,462 Table 2: Dataset Statistics for SourceForge Total projects 699,331 Number of Java projects 50,692 Methods with atleast one catch block 6,657,595 Total number of Catch blocks 9,956,760 1. INTRODUCTION An exception is an unanticipated or an exceptional (as the name suggests) occurrence that may arise during the execution of a program, disrupting its normal flow. Exception handling is a proactive mechanism to respond to such an event in a sound and reliable manner. This concept was originated with Lisp programming language in the 1960s, where return value of the ‘ERRSET’ keyword was used to determine error scenarios. Many programming languages subsequently o↵ered built-in support for exception handling. Some languages, for example C, use return codes to handle exceptions. However, one amongst many disadvantages of this mechanism is the use of multiple flow control statements to return respective error codes, thereby making the code verbose and difficult to maintain. This resulted in newer approaches to handling errors. Java provides a powerful support system for exceptions involving dedicated try-catch-finally blocks to separate functional code from exception-handling logic. Throwable is the superclass of all exceptions and errors (which are unhandled critical problems). In this paper, the focus is exclusively on exceptions. The terms error(s) and exception(s) are used interchangeably, however in all cases they refer to exceptions and not the category of serious errors, unless specified otherwise. One noted advantage of exception handling in Java is its hierarchy and classification of exception types based on the type of error. The highest in this hierarchy is the class Exception. All subclasses of Exception which do not fall under RuntimeException are categorized as checked exceptions. The term checked has come into usage as Java enforces or checks for these exceptions during compilation. The intention is to force developers to think of sophisticated ways to Figure 1: Boa script to find top unaccompanied method calls in a checked exception block. handle such exceptions in case they occur. In this paper, we mine data to gain insight into how developers handle checked exceptions and the utility of Java enforcing the same. An extension to this study includes extracting general exception handling patterns used by developers. Furthermore, the specificity of an error caught increases as we move down the class hierarchy. To illustrate, the exception SQLClientInfoException inherits properties of its parent class SQLException. Catching an SQLClientInfoException would provide extra information of the error to a developer by fetching details regarding SQL client properties, going beyond what is provided by superclass SQLException. Since each exception is a Java object, an exception thrown at a lower level can also be caught by its superclass. In this paper, we explore the frequency and usage of generic exceptions. The research questions that guide our work are: 1. How well are checked exceptions handled? Does Java enforcing them fulfill its purpose? 2. What scenarios are exception handling used for? 3. How often are top-level exceptions caught and their potential danger(s) to the product quality? 2. RELATED WORK Exception handling behavior is a topic of long term study by software engineering researchers and product managers. Shah et al.[7] studied the developer perspective on exception handling and attempted to understand the root cause for developer attitude and actions. The study was conducted by observing and interviewing nine Java developers - eight of whom were interns at a large multinational organization, and the last participant was a full-time employee at the same organization. The participants were asked questions that evaluated their understanding and approach towards exception handling. The results showed that most participants seemed to give a low priority to exception handling as a task, or included exceptions in their code only when the language forced them to handle checked exceptions. The basis of our study is to support or negate these qualitative claims with empirical data. Monperrus et al.[5] compared best practices fetched from known and authentic sources against empirical data extracted from Java projects. While this was an empirical study, the dataset used was small (32 Java projects). Moreover, the focus was not to specify patterns used in exception handling, but to challenge or validate known best practices. For example, they picked code snippets from the analysed projects to showcase that empty catch blocks were not always harmful as suggested in the knowledge sources. The contribution of our study, on the other hand, is in producing empirical data fetched from a large scale data source, with the intent of identifying common practices followed by developers to tackle exceptions. Understanding that exception handling is taken as a last priority in any software developement process causing software project failures, Rogerio et. all [2] provide a systematic approach to handling exceptions. The main idea of their study is proposing a solution in which exceptions are identified and their handlers are defined as a part of the software development process, and not put o↵ till the end. They suggest an approach to define and divide exception class types based on the software system model analysed, thus categorizing them into application-related, design-related and implementataion-related exceptions. Xie and Thummalapenta[8] have tried to address the issue of poor exception handling behaviour exhibited by developers by creating formal specifications of exceptions. They represent expected exception-handling behaviour in the form of sequence association rules and exceptional cases as alternative patterns. These rules and patterns are meant to be used by tools to automatically analyze exception handling behaviour as a future work. 3. RESEARCH METHODOLOGY Analysis data was extracted from MSR’16 Mining Challenge Boa Dataset[3] using the BOA domain specific language[3] run on their web interface[6]. This dataset contains metadata for almost 700,000 SourceForge (SF) and 8,000,000 GitHub (GH) repositories. Fig. 1 gives a sample Boa script written to extract data for top checked exceptions. The latest snapshot was picked up for the purpose of this study and a total of 554,864 Java projects in the GitHub repository were analyzed. The dataset is current as of September 2015. A study on 50,692 Java projects from the SourceForge Sep’ 13 dataset was also performed to validate GitHub results. Table 1 and 2 give brief statistics on both datasets studied. However, being a larger and more current dataset, our results are more concentrated towards GitHub. The Boa programming language is composed of di↵erent domain-specific constructs which make it particularly useful for mining language features. These constructs include Table 3: Top Exceptions Caught in Catch Blocks. ExceptionType Number Checked Exception Unchecked Exception Exception 3,859,217 Superclass Superclass IOException 2,170,519 Yes SQLException 681,638 Yes Throwable 670,214 Superclass Superclass InterruptedException 555,555 Yes IllegalArgumentException 460,872 Yes NumberFormatException 364,362 Yes NullPointerException 326,193 Yes RemoteException 263,920 Yes RecognitionException 203,892 Yes TOTAL 3,671,632 1,355,319 software abstractions like CodeRepository, Revision, Project, Statement etc., which can be used as part of queries to the dataset. Boa’s infrastructure obtains the source code of files in the SourceForge and GitHub repositories and parses the source code to obtain its abstract syntax tree(AST) representation. Each Boa program is designed to traverse through the AST of the target projects to reach the required query object. Considering the extremely large number of projects in the repositories, Boa programs run on a distributed cluster to reduce execution time. Developers are given the choice of selecting a small, medium or complete subset of the repositories on which to run the query. Direct access is not given to the source code of the files in the Boa dataset. All research questions which needed to observe real code snippets have been answered by obtaining the full path of the required file from Boa, and manually traversing the file to the required code. 3.1 Mining Exception Categories The number of exceptions handled in a method can be extracted using one or any combination of the following three methods: 1. Exceptions thrown using throws keyword in the method signature. 2. Exceptions thrown using throw keyword in the method body. 3. Exceptions caught in a try catch block of a method. The first method might not provide a true picture of real life scenarios, as exceptions thrown using throws in the method signature are falsely added with the call stack of methods propagating the exception until it is caught. Furthermore, an exception thrown using the second method will eventually be caught by a caller method using a try catch block. Hence, the top twelve exceptions caught in catch blocks, as shown in Table 3, are chosen for our study. For each exception in the top twelve above, both long and short notations were considered - for eg., the long notation for IOException would be java.io.IOException. 4. Figure 2: Top Operations performed in Checked Exception catch blocks (GH). RESULTS The cumulative results in Table 3 show that checked exceptions account for almost three times the number of unchecked exceptions in Java projects. This can be attributed to the compile-time checking for the presence of checked exception handlers. In the following sections, mined results on the usefulness of checked exceptions are presented. Further insights into: how programmers handle said exceptions; value of enforcement, and general exception handling patterns are provided. It can be inferred from the above table that developers often catch exceptions at the ‘top-level’ using the Throwable and Exception class. Further details about this implementation strategy and potential harmful e↵ects to code quality are discussed in Section 4.3. 4.1 Analyzing Checked Exception Handling As discussed above, Java enforces the compile-time use of checked exceptions. For example, while making a database connection, it raises a compilation error forcing the developer to handle SQLException. This also compels one to envision any possible errors that could occur and tackle them as desired. For example, if one expects a primary server crash, the catch clause could be coded to connect to a secondary server or return an appropriate message back to client. This enforcement is designed to make the application developer life easier and the code quality better. Usage of the top three checked exceptions picked from Table 3 was analyzed. This began with mining the top twenty method calls; throw an exception calls and variable declarations made inside a catch construct of a checked exception, as shown in Fig. 2. It can be observed that the top spot Figure 3: Code Snippet from a GitHub project. is shared between printStrackTrace and log methods, which indicates that many developers use checked exceptions for logging and debugging. The second major observation is the large number of empty catch blocks - this is discussed in Section 4.2. However, the operations shown in Fig. 2 may have accompanied other operations inside the catch block. For example, a log call may have been made along with a throw exception call. For additional clarity, results for common unaccompanied operations performed inside a checked exception handling construct, as shown in Fig. 4, were mined. The phrase “unaccompanied operation” implies that operation in the figure was the only action taken inside the catch block. It can be noted that 83% of the printStackTrace operations were performed unaccompanied. Many developers use popular IDEs such as Eclipse and IntelliJ which provide powerful suggestion and code completion tools, including adding try catch constructs with default printStackTrace call for checked exceptions. Fig. 3 gives an example of a code snippet extracted from the GitHub project “pennshare”, which shows the checked SQLException handling.The high number of printStackTrace calls reveals that a lot of developers ignore and leave the catch block unattended. Bloch asserts [1]-“To capture the failure, the detail message of an exception should contain the values of all parameters and fields that contributed to the exception.” For instance, in the code snippet in Fig. 3, instead of using the generic printStackTrace, handling the SQLException by printing out the details of the SQLState of the database and the error code specific to the vendor would give more useful information to the developer and help in faster debugging of the issue. Another interesting observation in Fig. 4 and Fig. 5 is the significant number of System.out.println statements that are the sole statements inside catch blocks of checked exceptions. It is recommended that a catch block should contain a comment explaining why a particular catch block is left unattended, at the very least. Though we do not have access to the source code of data, it is safe to assume that developers use System.out.println statements to print useful information that might help them later on for debugging purposes. Since the access to plain source code is not provided, it may be difficult to interpret the reasons for developers using variable declarations inside catch blocks. We performed a compare and contrast of GitHub results with data extracted from SourceForge projects. The results from SourceForge showcase a similar trend with 78% printstacktrace and 67% log statements made unaccompanied. This is shown in Fig. 5. Furthermore, it is also noticed that developers tend to Figure 4: Comparison of top unaccompanied operations performed vs their total instances in catch blocks of checked exceptions (GH). Figure 5: Comparison of top unaccompanied operations performed vs their total instances in catch blocks of checked exceptions (SF). wrap checked exceptions inside unchecked ones while throwing them back to the caller. Due to lack of access to plain source code, we may not be able to judge the reason behind these wrapped throws. However, Bloch recommends in his book [1] to “use checked exceptions for recoverable conditions and runtime exceptions for programming errors”. It states that if the user finds a checked exception unrecoverable, wrapping into an unchecked exception keeping the stack trace intact and throwing it back to the client or the caller method is justifiable. The data indicates that around 74% of throw statements in IOException handlers and 65% of throw statements in SQLException handlers were made to RuntimeException, which is consistent with Bloch’s views. This leads us to answer our first research question. Though checked exceptions were introduced to direct the thought process towards error recovery, the results show that most developers neglect handling them well. This defeats the purpose of the Java enforcement mechanism. 4.2 Analyzing General Exception Handling The data related to checked exceptions noted in Section 4.1 seems to extrapolate well with all types of exceptions. In this section, we will focus more on general exception handling patterns. Figure 6: Code Snippet from a GitHub project demonstrating an empty catch block. Figure 7: Top operations used in exception handling (GH). Java has a well-built, self-sufficient exception handling library. Bloch ”favors the use of standard exceptions” which already provide great level of specificity and information. This is because developing applications/APIs using standard exceptions allow novice developers or developers who are new to a project or exception handling understand APIs more clearly, thereby eliminating the confusion typically caused by custom exceptions. As shown in Table 3, the top 10 exceptions being used are all standard exceptions. This observation shows that the above-mentioned recommendation is being followed widely. The number of empty catch blocks in Fig. 7 draws attention. The percentage of empty blocks was calculated with respect to the total number of catch blocks present in the dataset. It was found that 20% of the total (16,172,462) catch blocks were left empty. The fact that one in every five catch blocks is left empty stresses the need for a better understanding of the use of exception handling. As stated by Bloch “An empty catch block defeats the purpose of exceptions, which is to force you to handle exceptional conditions”. This holds the product at risk for the following reasons: time consuming debugging due to absence of tracing and logging when an error occurs; and swallowing issues not intended to be caught, which results in false positive output[1]. An example of a catch block being left empty is shown in Fig. 6. This has been taken from the project Ghostrec35 in the GitHub repository, and demonstrates how the code is vulnerable to bugs arising because of the empty NullPointerException handler. The top method calls in catch constructs show significantly more number of logging techniques as compared to the ones found in previous section. These include: log4j/ slf4j methods at all five levels (info, debug, etc.); handler module methods such as ReportError; logger module methods at various levels (severe, warning, etc.). All these method calls made for logging were added to produce the final number shown in Fig. 7 for ‘Log Statements’. Fig. 7, Fig. 8 and Fig. 10 show a high usage of logging inside catch constructs; in particular, of log messages being used as standalone actions. This supports the claim in paper [7] - “developers have shifted their perspective on exception handling from the intended proactive approach (i.e., how to handle possible exceptions) to a reactive approach (i.e., using exception handling as debugging aids)”. The printStackTrace number also backs this claim. Bloch advises that “higher layers should catch lower-level exceptions and, in their place, throw exceptions that can be explained in terms of the higher-level abstraction”[1]. To study this scenario, top hundred throw calls were extracted in the form of ‘A -> B’ where A/B are exception class types and A throws B in its handler. As shown in the Table 4, the highest number of translations (145,916) were made from Exception to RuntimeException which runs counter to Bloch’s advice. Most conversions from any exception type were made to RuntimeException. Excluding the above number and looking at next top twenty results, 66% conversion from lower to higher level exception and 24% from higher to lower are observed. The remaining were thrown at the same level, for eg. ‘IOException throws IOException’. This allows them to add a layer of abstraction and hide the inner implementation details, also allowing them to let the caller method know of an unrecoverable event, which can eventually be handled up the stack. These results show positive alignment with the advice. A total of 3832 instances of return NULL in GitHub and 3479 instances in SourceForge were also observed in catch blocks. Since the number of such observations is small (relative to the dataset) and the reason behind the action is unknown - this does not stand out as a major concern. The use of customized exceptions in Java projects could not be analyzed due to the size of the dataset and have been excluded from the scope of this study. From the above, we see that many developers seem to use Java exception handling for logging and fetching the stack trace. Many more developers choose to leave the catch constructs empty. Quite a lot of them convert and throw back exceptions to their caller methods. Due to the size of the dataset, it was challenging to fetch user-defined exceptions and meaningful operations performed as they are specific to each project. This answers our second research question. 4.3 Catching Top-level or Generic Exceptions As showcased in Table 3, data of the top twenty exceptions caught shows that the superclass of all exceptions viz. Exception has the largest frequency of occurrence and that its base class Throwable also has a surprisingly high usage. As per findings in [7], many developers tend to keep exception handling as simple as possible, which potentially encourages Table 4: Top 15 ‘A -> B’ calls made inside a catch construct (GH). A -> B Expression Number of Throws Exception -> RuntimeException 145,916 IOException -> RuntimeException 120,586 TException -> IOException 30,504 Exception -> IOException 22,851 Exception -> SystemException 20,230 Exception -> IllegalArgumentException 19,435 Exception -> Exception 17,818 InterruptedException -> RuntimeException 17,791 UnsupportedEncodingException -> RuntimeException 17,724 Throwable -> RuntimeException 17,507 SQLException -> RuntimeException 16,949 IllegalAccessException -> RuntimeException 16,252 HibernateException -> SystemException 16,154 RemoteException -> RuntimeException 15,332 IOException -> IllegalStateException 15,122 Figure 8: Comparison of top unaccompanied operations performed vs their total instances in Exception handling (GH). Figure 9: Comparison of number of instances of methods that caught only Exception or Throwable classes vs the total number of instances of methods with only catch block Figure 10: Comparison of top unaccompanied operations performed vs their total instances in Exception handling (SF). wrapping of the calling code in a single Exception or Throwable class handler. The numbers in Table 3 for Exception and Throwable includes code wrapped in multiple handlers along with generic handlers. To learn more, the number of methods that contained only Exception and Throwable handlers was analyzed further. A staggering 78% of the methods that caught Exception did not catch any of its subclasses and a similar observation of 84% was made for Throwable. A total of 10,862,172 methods with catch clauses were extracted. 30% of them contained only the generic Exception class handler. Exception handling increases the burden on JVM in that the code wrapped in try-catch blocks often takes more time to execute when compared to the plain code. Nevertheless, good use of this mechanism pays o↵ significantly by saving the precious time of developers from painful debugging. So, just the catching of top level Exceptions is not very helpful. Here we analyze the ratio of the number of methods with only one catch block in them to the number of the methods with only one catch block catching top level exceptions, namely, Exception and Throwable, as shown in the Fig. 9. We found that nearly 37% (3,023,506 out of 8,107,881) of methods have caught only Exception whereas Figure 11: Top operations in Exception catch construct (GH). 7% (564,723 out of 8,107,881) of methods have caught only Throwable in the GitHub repository. This observation shows us that developers often don’t make good use of the Exception handling mechanism. A similar observation was made in SourceForge data as well. Bloch [1] maintains that - “Exception handlers that are too general can make code more error-prone by catching and handling exceptions that were not anticipated by the programmer and for which the handler was not intended”. As shown in Fig. 11, printing stack trace and logging were the top actions executed in an Exception catch construct. This makes the code more vulnerable as generic handlers provide low scope for specific log messages and recovery actions. Throwable handlers place a higher risk on the product as they also capture critical errors, which are not meant to be caught as exceptions. This reveals a dismal picture of the code and product quality. Finally, answering our third and last research question, Exception is the leading handler used, followed shortly by Throwable. Reiterating Bloch’s views[1], this practice places a higher risk on the final product by catching unrelated bugs and discouraging specific meaningful recovery. 5. DISCUSSION In this section, views from Bloch’s book [1] have been summarized which briefly mention the best practices to be followed in handling exceptions. We extend those views to discuss one particular method which Bruce Eckel, the author of the book “Thinking in Java” recommends as a good practice for handling exceptions in a Java project. This uses custom exceptions. 5.1 Best Practices In his book [1], Bloch mentions the following points which a developer must keep in mind while dealing with exceptions: 1. “Use exceptions only for exceptional scenarios” - This suggests that exception handling must not be used as a flow control technique or as a part of for- or while- loop ending logic. Quite a bit of JVM resources are used up in handling an exception. Hence, using exception handling for non exceptional scenarios not only confuses the end user of the method regarding its purpose, it also leads to performance degradation. 2. “Use checked exceptions for recoverable conditions and Figure 12: Custom Request Failure Exception. runtime exceptions for programming errors” - This has been discussed in Section 4.1. 3. “Avoid unnecessary use of checked exceptions” - This suggests to use checked exceptions only when the exception cannot be avoided by properly coding the API and there is no alternate recovery step that could be taken in case the said exception occurs. 4. “Favor the use of standard exceptions” - Since Java already has an extensive exception handling API, using standard exceptions makes the code more understandable and achieves code reusability. 5. “Throw exceptions appropriate to the abstraction” - This has been discussed in Section 4.2. 6. “Document all exceptions thrown by each method” While writing Javadocs and like, developers must remember to document the exceptions thrown by each method, along with the reason for throwing such an exception so as to make it clear to the calling API. 7. “Include failure-capture information in detail messages” - This suggests to capture value and parameters that caused the exception, especially while throwing back an exception. This makes exception tracking easier. 8. “Don’t ignore exceptions” - This has been discussed in Section 4.2. 5.2 Using Custom Exceptions Bruce Eckel, described and recommended in his blog [4], one of the ways to use custom exceptions to handle exceptions, which we describe below. Re-emphasizing Bloch’s [1] point 7 above, all exceptions thrown by a method must be documented in its Javadoc, so that the calling API is well aware of their presence. In case of many exceptions being handled, the calling API will need to ensure catching all those exceptions. In case the method is changed later and the exceptions caught in it are also changed, all the APIs using the method need to be refactored to maintain proper functioning. To avoid these scenarios, custom exceptions prove as a good bet here. Consider the code constructs given in Fig. 12 and Fig. 13 wherein one has two types of custom exceptions, RequestFailureException and ApplicationFailureException. The former catches any exceptions related to the client request, for Figure 13: Custom Application Failure Exception. eg. wrong filename input, while the latter catches any exceptions related to application failure, for eg. database server crash. When a callee method encounters an exception and is unable to process any steps to recover from it, it throws the custom exception back based on the exception type that occurred. The caller method in turn would not have to worry about the multiple exceptions that were caught in the callee method and only needs to catch either or both of the two custom exceptions. Both these custom exceptions are coded to wrap the original exception that occurred and to return the original exception when needed. The advantage here is that when the custom exception is coded to return back the original exception that was caught, it facilitates abstraction while not holding back information on the real exception and its parameters. Fig. 14 shows how exceptions could be wrapped in custom exceptions and thrown back to the caller. Fig. 15 showcases the use of the custom exceptions defined. It illustrates how the custom exception could be re-thrown to fetch the original exceptions, hence giving specificity and customization of exception handling. Since each caller in the call stacktrace does not need to catch all exceptions thrown in the callee method, it makes the code much cleaner. Furthermore, any changes made with respect to exception handling like adding or deleting some exception handlers will not a↵ect the caller API, making the code more scalable. 6. Figure 14: Sample code illustrating throwing custom exceptions. 7. Figure 15: Sample Code illustrating use of Custom Exception picked from Bruce’s blog [4]. THREATS TO VALIDITY The material extracted from the data set provides empirical results on the exception types, number of exceptions and actions taken within a catch construct. However, due to lack of access to raw source code, the rationale behind these actions is unknown. Hence, our reasoning behind how and why handlers were used and categorizing them as incorrect may not always be sound. Also, the usage of custom exceptions could not be evaluated as custom exception names di↵er with each project. Considering the volume of the projects studied, picking such exceptions proved costly and hence were removed from the scope of this paper. Since the intent of the study has been to align with best practices stated by Bloch[1], the focus here has been to surface patterns which stand for or against those views supported by empirical data. CONCLUSION In this paper, we studied all Java projects in the GitHub and SourceForge repositories to spot common exception handling practices. We have particularly analyzed the checked exception handling in good detail. Next, these observations were compared against best practices presented by Bloch[1]. To sum up the results, most developers ignore checked exceptions and leave them unattended. This is true for other types of exceptions as well. General exception handling shows developer inclination shifting from proactive recovery to debugging. The ignore-for-now and mere logging approach followed for checked exceptions may help with debugging, but the absence of required recovery steps and continued smooth flow may lead to errors going unnoticed and potential incorrect product output. Thus, handling exceptions well is a skill that developers need to inculcate in themselves, else this language enforcement of checked exception handling will fall short of its intended value. Developers also tend to use generic handlers over specific ones. The reason for these approaches cannot be confirmed to be correct or incorrect without studying source codes. However overall, the results show major di↵erences between theoretical best practices and the use of exception handling in practice. We further summarized the best practices stated by Bloch and described one of the recommended approaches by Bruce to tackle exceptions. 8. REFERENCES [1] J. Bloch. E↵ective Java (2Nd Edition) (The Java Series). Prentice Hall PTR, Upper Saddle River, NJ, USA, 2 edition, 2008. [2] R. de Lemos and A. Romanovsky. Exception handling in the software lifecycle. International Journal of Computer Systems Science and Engineering, 16(2):167–181, March 2001. [3] R. Dyer, H. A. Nguyen, H. Rajan, and T. N. Nguyen. Boa: A language and infrastructure for analyzing ultra-large-scale software repositories. In Proceedings of the 35th International Conference on Software Engineering, ICSE’13, pages 422–431, 2013. [4] B. Eckel. Does java need checked exceptions? http://www.mindview.net/Etc/Discussions/ CheckedExceptions/, 2005. [5] M. Monperrus, M. Germain De Montauzan, B. Cornu, R. Marvie, and R. Rouvoy. Challenging Analytical Knowledge On Exception-Handling: An Empirical Study of 32 Java Software Packages. Technical report, Laboratoire d’Informatique Fondamentale de Lille, 2014. [6] H. Rajan, T. N. Nguyen, R. Dyer, and H. A. Nguyen. Boa website. http://boa.cs.iastate.edu/, 2015. [7] H. Shah, C. Görg, and M. J. Harrold. Why do developers neglect exception handling? In Proceedings of the 4th International Workshop on Exception Handling, WEH ’08, pages 62–68, New York, NY, USA, 2008. ACM. [8] T. Xie and S. Thummalapenta. Making exceptions on exception handling, 2012.