Skip to content

Instantly share code, notes, and snippets.

@cleantutorials

cleantutorials/Dog.java

Last active Sep 1, 2019
Embed
What would you like to do?
The Dog POJO representing a Dog. The class has a faulty logic in the equals method which can lead to memory leaks if the object is used as key in Sets/Maps.
package com.cleantutorials.jconsole.memory;
/**
* Dog represents a dog which can be uniquely identified by the MicroChip ID and
* can optionally have a name.
*/
public class Dog {
/** The Unique MicroChip ID of the dog. */
private int microChipID;
/** The name of the dog. */
private String name;
/** Extra memory space for each instance to speed up the memory leak. */
private byte[] toExpediteLeak;
Dog(int microChipID) {
this.microChipID = microChipID;
}
Dog(int microChipID, String name) {
/**
* On Creating a Dog object we allocate a 10Mb storage with each instance to
* expedite the memory leak.
*/
this.toExpediteLeak = new byte[10000000];
this.microChipID = microChipID;
this.name = name;
}
@Override
public boolean equals(Object obj) {
if (obj == this)
return true;
if (!(obj instanceof Dog))
return false;
Dog dog = (Dog) obj;
return dog.microChipID == microChipID && dog.name.equals(name);
}
@Override
public int hashCode() {
return microChipID;
}
/**
* @return MicroChip ID of the dog.
*/
public int getMicroChipID() {
return microChipID;
}
/**
* @return name of the dog.
*/
public String getName() {
return name;
}
/**
* @param name of the dog.
*/
public void setName(String name) {
this.name = name;
}
}
package com.cleantutorials.jconsole.memory;
import java.util.HashSet;
import java.util.Random;
import java.util.Set;
/**
* DogShelter class represents a Dog Shelter. Each instance maintains the list
* of dogs that are currently present in the shelter. This class is designed to
* demonstrate memory leak in Java due to design flaws and human errors.
*/
public class DogShelter {
/** In Memory Store containing the dogs present in the shelter. */
private Set<Dog> shelterDogs = new HashSet<Dog>();
public static void main(String[] args) {
DogShelter shelter = new DogShelter();
shelter.addAndRemoveRandomEntries(1000);
}
/**
* Adds the <code>Dog</code> object entry to the HashSet.
*
* @param microChipID An ID used to uniquely identify a dog.
* @param name Name of the dog.
*/
public void addEntry(int microChipID, String name) {
Dog dog = new Dog(microChipID, name);
shelterDogs.add(dog);
}
/**
* Removes the <code>Dog</code> object from the HashSet
*
* @param microChipID An ID used to uniquely identify a dog.
*/
public void removeEntry(int microChipID) {
Dog dog = new Dog(microChipID);
shelterDogs.remove(dog);
}
/**
* Generates random Dog Objects and add and remove the dog object serially.
*
* @param entriesCount Number of random entries to be added and removed from
* HashSet
*/
public void addAndRemoveRandomEntries(int entriesCount) {
Random rand = new Random();
String[] commonDogNames = { "Buddy", "Coco", "Charlie", "Cooper", "Maggie" };
for (int i = 0; i <= entriesCount; i++) {
/** Generate a random dog name from the list of common dog names. */
String randomDogName = commonDogNames[rand.nextInt(commonDogNames.length)];
/** First add and then remove the entry from the HashSet. */
addEntry(i, randomDogName);
removeEntry(i);
System.out.printf("Successfuly removed entry for %s with unique id %d.\n", randomDogName, i);
try {
/**
* Sleep before adding & removing new entry so that we can see the memory grow
* in JConsole.
*/
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment