0

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());

    }
}
Holger
  • 285,553
  • 42
  • 434
  • 765
A.F.R.N
  • 11
  • 1
  • 6
  • 1
    What do you want to do? For what reason do you want to override ```finalize```? – akuzminykh Mar 17 '20 at 05:49
  • `System.gc();` does not guarantee garbage collection will run, in fact given this short program it probably doesn't. To save time, there is no way to force garbage collection to run. And `finalize` is **deprecated**. And class names start with a capital letter. – Elliott Frisch Mar 17 '20 at 05:49
  • *A static member is referenced by a class while the class is referenced by its class loader* Unless the classloader unloads the class it will remain – Scary Wombat Mar 17 '20 at 05:50
  • i want to override finalize in order to see decrement in my student count variable when one of the object is not pointed by any variable. – A.F.R.N Mar 17 '20 at 05:52
  • public void finalize(){ count -= 1; } – A.F.R.N Mar 17 '20 at 05:52
  • what is meant by deprecated – A.F.R.N Mar 17 '20 at 05:53
  • yes it is convention of class name that it should start with cap. but please tell me about my problem with not being able to decrement it. do i need to delete object if so than how? when will the object be destroyed and how would i use it to decrement my count var. – A.F.R.N Mar 17 '20 at 05:55
  • *"when one of the object is not pointed by any variable"*, but why? What is your motivation behind that? And please dont post 5 comments under each other. Just post one single comment. – akuzminykh Mar 17 '20 at 05:57
  • *what is meant by deprecated* DANGER. Bridge is old and unsafe and scheduled for demolition. But if you ***want*** to drive across it, our engineer cannot legally stop you. If you continue past this point, you agree to hold us harmless. – Elliott Frisch Mar 17 '20 at 06:00
  • 1
    @Nicktar why did you remove the `[garbage-collection]` tag? – Holger Mar 18 '20 at 15:45

1 Answers1

1

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.

Holger
  • 285,553
  • 42
  • 434
  • 765