Understanding the Impact of Collection Contracts on Design

Understanding the Impact of Collection Contracts on Design

Understanding the Impact of Collection Contracts on Design Stephen Nelson, David J. Pearce, and James Noble Victoria University of Wellington Wellington, New Zealand fstephen,djp,[email protected] Abstract. Java provides a specification for a user-defined general purpose equiv- alence operator for objects, but collections such as Set have more stringent re- quirements. This inconsistency breaks polymorphism: programmers must take care to follow Set’s contract rather than the more general Object contract if their object could enter a Set. We have dynamically profiled 30 Java applica- tions to better understand the way programmers design their objects, to determine whether they program with collections in mind. Our results indicate that objects which enter collections behave very differently to objects which do not. Our find- ings should help developers understand the impact of design choices they make, and guide future language designers when adding support for collections and/or equality. 1 Introduction Designing good software is hard. Designing good programming languages is harder still. Modern programming languages have evolved to include numerous high-level constructs, and to provide vast libraries of reusable code. Inheritance, polymorphism, collections and first-class regular expressions are just a few examples. Many of these constructs have subtle and important effects on the way software is designed. In this paper we consider the effect of one particular feature of Java on program de- sign. Java’s Object class provides a specification for defining general purpose object equality. However, Java Collections such as Set and Map require stronger contracts on the implementation of object equality than the Object specification provides. This paper addresses the question, how do programmers satisfy equality contracts? We examine the behaviour of objects in running Java programs, comparing objects in different Collections and outside Collections to identify differences in their design. In particular, we compare objects which enter equality collections such as Set, non- equality collections such as ArrayList, and objects which do not enter a collection at all. The contributions of this paper are: 1. A set of object characterisations, based on equality and state mutability, which can be measured at runtime. 2. Design and implementation a runtime profiler, called #Profiler, that observes the way objects behave when they are and are not in collections. #Profiler employs AspectJ to intercept field reads/writes, constructors and calls to collections. 3. Results from examining 30 real-world Java programs using #Profiler. Our results indicate: – Objects which do not enter collections do not change their equality; – Objects which enter non-equality collections are much more likely than other objects to change their internal state; – Objects which enter equality collections are much less likely to change internal state than objects which enter other collections; – Objects which enter equality collections and do change their state are no more likely to change their equality than objects which enter non-equality collec- tions. The rest of this paper is organised as follows: Section 2 discusses various contracts imposed on equality implementations by Java, particularly those imposed by Collec- tions, and outlines our approach to categorising objects according to the way they ad- dress these contracts; Section 3 discusses how the object categorisations are measured with our profiling tool, #Profiler; Section 4 presents our experimental results looking at the behaviour of objects across 30 open source Java applications; Section 5 covers related work and, we summarise our findings in the conclusion. An extended version of this paper is available as a technical report [1]. 2 Equality for Collections Every object is inherently distinguishable by its location in memory and many lan- guages, like Java, expose this using an equivalence operator. However, it can be useful for objects to define their own equivalence relation for comparing internal state. In ad- dition to reference comparisons, Java provides equals(..) — a method defined on the root of the class hierarchy which subclasses can override to implement their own equivalence relations. The documentation provided for this method states that it must be an equivalence relation, but also that it is consistent — that is, it will return the same result for multiple calls so long as the information it uses does not change [2]. Java also provides the Java Collections API, a group of collections for programmers to use. Almost all of these collections are capable of storing Objects directly, without any additional type information, yet several require contracts on equals() which are stronger than the requirements imposed by Object on the equals method. For example, documentation for java.util.Set states: “Note: great care must be exercised if mutable objects are used as set elements. The behavior of a set is not specified if the value of an object is changed in a manner that affects equals comparisons while the object is an element in the set. A special case of this prohibition is that it is not permissible for a set to contain itself as an element.” [2] As there is no type constraint to prevent mutable objects from entering a Set, pro- grammers must take care that they obey this contract or they may encounter subtle bugs in their programs. This paper attempts to discover how much programmers use mutable objects in collections and, if they do, how they avoid violating the additional constraints 2 that some collections impose. We begin by discussing the collections contracts in more detail, then introduce two categorisations for objects based on equality and state, re- spectively. We conclude this section by discussing a unified categorisation for objects based on both equality and state which is used for the remainder of the paper. 2.1 Collection Contracts The Java Collections API provides four main interfaces: List, Set, Map and Queue. There are also implementations provided and, in some cases, there are several each with different properties. The Set interface imposes a particularly strict contract on the objects it contains: they cannot change while they are in the collection. Map requires the same of key ob- jects, but not of value objects. Lists do not have additional requirements on the objects they contain, but they also have a related note of caution: “Note: While it is permissible for lists to contain themselves as elements, ex- treme caution is advised: the equals and hashCode methods are no longer well defined on such a list.” [2] This aside is because Lists, unlike Queues, implement Java’s equals() and hashcode() methods which depend on the list’s contents, recursively calling equals or hashcode on each member. While they do not directly impose a contract on their members, programmers must be aware that if the list is stored in another collection which does impose a contract it will transitively apply to the list’s contents. In the rest of this paper we will refer to objects entering equality and non-equality collections. Equality collections require that the equality of objects does not change while they are in the collection. These include subclasses of Set, and the key-sets of Map and HashTable subclasses. Non-equality collections are Lists, Queues, and the value-sets of Maps and HashTables. 2.2 Measuring Changes to Equality An object following the contract for equality outlined by Object may change its equal- ity at any point in its existence. If it is in a Collection, however, this could be an error. To determine which strategies programmers use to avoid these errors, we track objects throughout their lifetime to determine when they do change. We have identified three measurable stages in the life-cycle of an object which we can use to classify objects based on when they change their equality: Construction: When an object is created the constructor is invoked to initialise the object. Even otherwise immutable objects will assign to fields in this phase, as Java al- lows objects to write to final fields during the constructor; so the first stage we consider ranges from the beginning to the end of the constructor. Initialisation: After an object is created and the constructor has run, there may still be additional initialisation performed on the object which could change its equality. So long as this happens before the object enters a collection it will not violate any equality contracts, so our second phase is from the end of the constructor until the object first enters a collection. Some objects will never enter a collection and thus never leave the ‘initialisation’ phase. 3 Type of Object Constructor Initialisation Post-Collection Identity as Equality Initialised Equality x Late-initialised Equality x x Reindexing x x x Fig. 1. Four types of objects distinguished by their different behaviours in various parts of their life-cycle. x denotes possible changes to equality during that phase. Post-Collection: After an object has entered a collection we consider it to be fully ini- tialised; any further changes to its hash code could violate the internal consistency of the collection. A programmer would have to consider the implications of changing an object which is in, or could still be in a collection. The post-collection phase ends when the object is garbage collected or the program terminates. These three measurable phases of an object’s life-cycle lead to the following four categorisations of objects based on their changes to equality, which are also presented in Figure 1: – Identity as Equality: objects in this category do not define a hash code method. They rely on reference equality for participation in equality-based collections. – Initialised Equality: these objects define a hash code, but it does not change after the constructor has completed. – Late-initialised Equality: late initialisation objects are distinguished by changes to their hash code after the constructor has completed but before entering a collection.

View Full Text

Details

  • File Type
    pdf
  • Upload Time
    -
  • Content Languages
    English
  • Upload User
    Anonymous/Not logged-in
  • File Pages
    18 Page
  • File Size
    -

Download

Channel Download Status
Express Download Enable

Copyright

We respect the copyrights and intellectual property rights of all users. All uploaded documents are either original works of the uploader or authorized works of the rightful owners.

  • Not to be reproduced or distributed without explicit permission.
  • Not used for commercial purposes outside of approved use cases.
  • Not used to infringe on the rights of the original creators.
  • If you believe any content infringes your copyright, please contact us immediately.

Support

For help with questions, suggestions, or problems, please contact us