Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package com.example.foo;
- import java.io.ByteArrayOutputStream;
- import java.io.OutputStream;
- import java.util.LinkedList;
- import java.util.List;
- /**
- * Demonstration of failing finalize-implementations. Just run main, wait and see that it does not
- * actually print any messages other than "good bye!", even though there are 5
- * <code>System.out.println(...)</code> in the finalize-methods.
- *
- * <p>
- * However, finalize is run even if the instance was not created properly (Exception in
- * constructor). This may lead to problems, as the resources to close might not even exist.
- *
- * <p>
- * This answers this question: "Why is there no guarantee that {@link Object#finalize()} is run?"
- *
- * <p>
- * If you want an answer to the question: "Then what can I do to properly use finalize()?" <br/>
- * The answer is: Don't! <br/>
- * Not just because of the problems presented here. There are actually more problems! <br/>
- * Here's a better alternative: http://claude-martin.ch/java-cleanup/
- */
- public class SomeClass {
- /**
- * Finalize of Object is not invoked by some JVMs because it is known to be empty. This is
- * relevant if you thought you could use a tools that can intercept invocation of finalize (as in
- * aspect-oriented programming).
- */
- static final class Finalize1 {
- // no finalize
- }
- /** Class and method not final. */
- static class Finalize2 {
- @Override
- protected void finalize() throws Throwable {
- // not final -> extending class doesn't have to call this method.
- System.out.println("Finalize2");
- }
- }
- /**
- * Finalize allocates new data and fails. GC runs it but you have no guarantee that the JVM can
- * run it successfully.
- */
- static final class Finalize3 {
- @Override
- protected void finalize() throws Throwable, OutOfMemoryError {
- // What if memory is already running out?
- // Chances are high - why else would gc be running?
- // Then even a small array could fail:
- byte[] bytes = new byte[Integer.MAX_VALUE];
- // OutOfMemoryError was thrown!
- System.out.println("Finalize3 " + bytes[0]);
- // Also not run:
- super.finalize();
- }
- }
- static Finalize4 finalize4;
- /**
- * This is just to show that you, as the author of a class, can not prevent that an instance is
- * referenced from a static field. This is also true for all data structures that exist until the
- * JVM exits.
- */
- static final class Finalize4 {
- @Override
- protected void finalize() throws Throwable {
- System.out.println("Finalize4");
- }
- }
- /**
- * JVM could end abruptly. Again, you have no control over this when you write a class.
- */
- static final class Finalize5 {
- @Override
- protected void finalize() throws Throwable {
- System.out.println("Finalize5");
- }
- }
- /** Runs Garbage Collection. */
- static void gc(int n) {
- final List<byte[]> list = new LinkedList<>();
- try {
- while (true)
- list.add(new byte[1024 * 1024]);
- } catch (OutOfMemoryError e) {
- // Now GC is needed...
- }
- for (int i = 0; i < n; i++) {
- System.gc();
- try { // Give it time:
- Thread.sleep(100);
- } catch (InterruptedException e) {
- }
- }
- }
- public static void main(String[] args) {
- gc(0); // fills memory
- // 1) no finalize implemented:
- new Finalize1();
- // 2) no call to super.finalize():
- new Finalize2() {
- private OutputStream resource = new ByteArrayOutputStream();
- @Override
- protected void finalize() throws Throwable {
- // Not calling super.finalize() !
- this.resource.close();
- }
- };
- // 3) Failing finalize:
- new Finalize3();
- // 4) static reference:
- finalize4 = new Finalize4();
- // Now let's try to get rid of them:
- gc(20);
- // 5) No time:
- new Finalize5();
- System.out.println("good bye!");
- System.exit(0);
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement