Advertisement
DulcetAirman

Examples of finalize() not run

Jul 23rd, 2014
313
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. package com.example.foo;
  2.  
  3. import java.io.ByteArrayOutputStream;
  4. import java.io.OutputStream;
  5. import java.util.LinkedList;
  6. import java.util.List;
  7.  
  8. /**
  9.  * Demonstration of failing finalize-implementations. Just run main, wait and see that it does not
  10.  * actually print any messages other than "good bye!", even though there are 5
  11.  * <code>System.out.println(...)</code> in the finalize-methods.
  12.  *
  13.  * <p>
  14.  * However, finalize is run even if the instance was not created properly (Exception in
  15.  * constructor). This may lead to problems, as the resources to close might not even exist.
  16.  *
  17.  * <p>
  18.  * This answers this question: "Why is there no guarantee that {@link Object#finalize()} is run?"
  19.  *
  20.  * <p>
  21.  * If you want an answer to the question: "Then what can I do to properly use finalize()?" <br/>
  22.  * The answer is: Don't! <br/>
  23.  * Not just because of the problems presented here. There are actually more problems! <br/>
  24.  * Here's a better alternative: http://claude-martin.ch/java-cleanup/
  25.  */
  26. public class SomeClass {
  27.  
  28.   /**
  29.    * Finalize of Object is not invoked by some JVMs because it is known to be empty. This is
  30.    * relevant if you thought you could use a tools that can intercept invocation of finalize (as in
  31.    * aspect-oriented programming).
  32.    */
  33.   static final class Finalize1 {
  34.     // no finalize
  35.   }
  36.  
  37.   /** Class and method not final. */
  38.   static class Finalize2 {
  39.     @Override
  40.     protected void finalize() throws Throwable {
  41.       // not final -> extending class doesn't have to call this method.
  42.       System.out.println("Finalize2");
  43.     }
  44.   }
  45.  
  46.   /**
  47.    * Finalize allocates new data and fails. GC runs it but you have no guarantee that the JVM can
  48.    * run it successfully.
  49.    */
  50.   static final class Finalize3 {
  51.     @Override
  52.     protected void finalize() throws Throwable, OutOfMemoryError {
  53.       // What if memory is already running out?
  54.       // Chances are high - why else would gc be running?
  55.       // Then even a small array could fail:
  56.       byte[] bytes = new byte[Integer.MAX_VALUE];
  57.       // OutOfMemoryError was thrown!
  58.       System.out.println("Finalize3 " + bytes[0]);
  59.       // Also not run:
  60.       super.finalize();
  61.     }
  62.   }
  63.  
  64.   static Finalize4 finalize4;
  65.  
  66.   /**
  67.    * This is just to show that you, as the author of a class, can not prevent that an instance is
  68.    * referenced from a static field. This is also true for all data structures that exist until the
  69.    * JVM exits.
  70.    */
  71.   static final class Finalize4 {
  72.     @Override
  73.     protected void finalize() throws Throwable {
  74.       System.out.println("Finalize4");
  75.     }
  76.   }
  77.  
  78.   /**
  79.    * JVM could end abruptly. Again, you have no control over this when you write a class.
  80.    */
  81.   static final class Finalize5 {
  82.     @Override
  83.     protected void finalize() throws Throwable {
  84.       System.out.println("Finalize5");
  85.     }
  86.   }
  87.  
  88.   /** Runs Garbage Collection. */
  89.   static void gc(int n) {
  90.     final List<byte[]> list = new LinkedList<>();
  91.     try {
  92.       while (true)
  93.         list.add(new byte[1024 * 1024]);
  94.     } catch (OutOfMemoryError e) {
  95.       // Now GC is needed...
  96.     }
  97.     for (int i = 0; i < n; i++) {
  98.       System.gc();
  99.       try { // Give it time:
  100.         Thread.sleep(100);
  101.       } catch (InterruptedException e) {
  102.       }
  103.     }
  104.   }
  105.  
  106.   public static void main(String[] args) {
  107.     gc(0); // fills memory
  108.  
  109.     // 1) no finalize implemented:
  110.     new Finalize1();
  111.  
  112.     // 2) no call to super.finalize():
  113.     new Finalize2() {
  114.       private OutputStream resource = new ByteArrayOutputStream();
  115.  
  116.       @Override
  117.       protected void finalize() throws Throwable {
  118.         // Not calling super.finalize() !
  119.         this.resource.close();
  120.       }
  121.     };
  122.  
  123.     // 3) Failing finalize:
  124.     new Finalize3();
  125.  
  126.     // 4) static reference:
  127.     finalize4 = new Finalize4();
  128.  
  129.     // Now let's try to get rid of them:
  130.     gc(20);
  131.  
  132.     // 5) No time:
  133.     new Finalize5();
  134.     System.out.println("good bye!");
  135.     System.exit(0);
  136.   }
  137.  
  138. }
Advertisement
Advertisement
Advertisement
RAW Paste Data Copied
Advertisement