Trying to decrement my static count variable in java jdk 1.8.0

373 Views Asked by At

Using finalize function, when I point an object to null it’s not decrementing although it is incrementing properly. I also mentioned garbage collector which will listen to its own self, I know but why it’s not working. I am using java jdk 1.8.0.

public class student{
    private String name; private int roll; private static int count = 0;
    //setters
    public void setname(String nam){
        name = nam;
    }
    public void setroll(int rol){
        roll = rol;
    }
    //getters 
    public String getname(){
        return name;
    } 
    public int getroll(){
        return roll;
    }
    public static int getCount(){
        return count;
    }
    //default constructor
    public student(){
        name = "default";
        roll = 9999;
        count += 1;
    }
    //parameterized constructor
    public student(String nam, int rol){
        setname(nam); setroll(rol);
        count += 1;
    }
    //copy constructor
    public student(student s){
        name = s.name; roll = s.roll;
        count += 1;
    }
    //methods to print on console
      public void print(){
    System.out.println("name: " + name + "\n" + "Roll Num: " + roll);
      }
     // overriding finalize method of Object class
     public void finalize(){
         count -= 1;
     }
}

//main function

public class clsnew{
    public static void main(String args[]){
        System.out.println("nuber of students" + student.getCount());
        student s1 = new student("Ahmad", 170404873); 
        student s2 = new student();
            s1.print(); //printing using parameterized constructor
            s2.print(); //printing using default constructor
            System.out.println("number of students" + student.getCount());

            s2.setname("Ali"); s2.setroll(200404230);

        System.out.print("s2: Name = "+s2.getname());
        System.out.println("Roll number: "+s2.getroll());

        student s3 = new student(s2);

        s2.print(); s3.print();
            System.out.println("number of students" + student.getCount());

        s2 = null;
        System.gc();

        int c = student.getCount();

            System.out.println("number of students" + student.getCount());

    }
}
1

There are 1 best solutions below

0
Holger On

First of all, you should never write applications relying on the garbage collector. Further, even if you need interaction with the garbage collector, you should avoid finalize().

For educational purposes, you have to be aware of the following things:

  • Finalization is not instantaneous. System.gc() is not guaranteed to identify a particular dead object, or even have an effect at all, but when it does, it may only enqueue the object for finalization, so by the time System.gc() returns, finalization might not have finished yet. It even might not have started yet.

  • Since the finalizer runs in an arbitrary thread, it requires thread safe updates.

Make the following changes:

  • Change private static int count = 0; to
    private static final AtomicInteger count = new AtomicInteger();,

    further count += 1; to count.incrementAndGet(); in each constructor
    and count -= 1; to count.decrementAndGet(); in the finalize() method.

    And getCount() to

      public static int getCount(){
          return count.get();
      }
    
  • Change System.gc(); to

      System.gc();
      Thread.sleep(100);
    

    You may surround the sleep call with a try...catch block or change the declaration of the main method adding throws InterruptedException

Then, you may observe the finalization of a student instance. To illustrate the counter-intuitive behavior of programs relying on garbage collection, I recommend running the program again, now with the -Xcomp option.

When you have JDK 11 or newer, you might also do a another run with
-XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC.