Can anyone tell me how to count the number of instances of a class?
Here\'s my code
public class Bicycle {
//instance variables
public int
Alternatively, you can create a counter with an initializer block and a static variable.
class SomeClass
{
private static int instanceCounter;
{
instanceCounter++;
}
}
Initializer blocks get copied by the compiler into every constructor, so, you will have to write it once no matter how many constructors you will need (As referred into the above link). The block in {} runs every time you create a new object of the class and increases the variable counter by one. And of course get the counter by something like:
public static int getInstanceCounter()
{
return instanceCounter;
}
or directly
int numOfInstances = SomeClass.instanceCounter;
If you do not make numOfInstances private
Since static
variables initialized only once, and they're shared between all instances, you can:
class MyClass {
private static int counter;
public MyClass() {
//...
counter++;
}
public static int getNumOfInstances() {
return counter;
}
}
Read more about static
fields in the JLS - 8.3.1.1. static Fields:
If a field is declared
static
, there exists exactly one incarnation of the field, no matter how many instances (possibly zero) of the class may eventually be created. Astatic
field, sometimes called a class variable, is incarnated when the class is initialized (§12.4).
Note that counter
is implicitly set to zero
Pleae try the tool of java
jmap -histo <PDID>
Out put
num #instances #bytes class name
----------------------------------------------
1: 1105141 97252408 java.lang.reflect.Method
2: 3603562 86485488 java.lang.Double
3: 1191098 28586352 java.lang.String
4: 191694 27035744 [C
In addition, you should override finalize method to decrement the counter
public class Bicycle {
...
public static int instances = 0;
{
++instances; //separate counting from constructor
}
...
public Bicycle(int gear, int speed, int seatHeight, String color) {
gear = 0;
speed = 0;
seatHeight = 0;
color ="Unknown";
}
@Override
protected void finalize() {
super.finalize();
--instances;
}
}
You should have in mind that static variables are CLASS scoped (there is no one for each instance, only one per class)
Then, you could demonstrate instance decrement with:
...
System.out.println("Count:" + Bicycle.getNumOfInstances()); // 2
bicycle1 = null;
bicycle2 = null;
System.gc(); // not guaranteed to collect but it will in this case
Thread.sleep(2000); // you expect to check again after some time
System.out.println("Count again:" + Bicycle.getNumOfInstances()); // 0
You just need static counter in class.
public class Bicycle {
private static volatile int instanceCounter;
public Bicycle() {
instanceConter++;
}
public static int getNumOfInstances() {
return instanceCounter;
}
protected void finalize() {
instanceCounter--;
}
}
As mentioned in many comments finalize()
is not recommended to use so there could be another approach to count the Bicycle instances -
public class Bicycle {
private static final List<PhantomReference<Bicycle>> phantomReferences = new LinkedList<PhantomReference<Bicycle>>();
private static final ReferenceQueue<Bicycle> referenceQueue = new ReferenceQueue<Bicycle>();
private static final Object lock = new Object();
private static volatile int counter;
private static final Runnable referenceCleaner = new Runnable() {
public void run() {
while (true) {
try {
cleanReferences();
} catch (Exception e) {
e.printStackTrace();
}
}
}
};
static {
Thread t = new Thread(referenceCleaner);
t.setDaemon(true);
t.start();
}
private Bicycle() {
}
public static Bicycle getNewBicycle() {
Bicycle bicycle = new Bicycle();
counter++;
synchronized (lock) {
phantomReferences.add(new PhantomReference<Bicycle>(new Bicycle(), referenceQueue));
}
System.out.println("Bicycle added to heap, count: " + counter);
return bicycle;
}
private static void cleanReferences() {
try {
PhantomReference reference = (PhantomReference) referenceQueue.remove();
counter--;
synchronized (lock) {
phantomReferences.remove(reference);
}
System.out.println("Bicycle removed from heap, count: " + counter);
} catch (Exception e) {
e.printStackTrace();
}
}
public static int getNumOfBicycles() {
return counter;
}
}
public class BicycleTest {
public static void main(String[] args) {
int i = 0;
while (i++ < 1000) {
Bicycle.getNewBicycle();
}
while (Bicycle.getNumOfBicycles() > 0) {
try {
Thread.sleep(1000);
System.gc(); // just a request
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
One basic approach is to declare a static numeric member field thats incremented each time the constructor is invoked.
public class Bicycle {
//instance variables
public int gear, speed, seatHeight;
public String color;
public static int bicycleCount = 0;
//constructor
public Bicycle(int gear, int speed, int seatHeight, String color) {
gear = 0;
speed = 0;
seatHeight = 0;
color ="Unknown";
bicycleCount++;
}
...
}