How to prevent an object from getting garbage collected?

后端 未结 11 1855
太阳男子
太阳男子 2020-12-02 13:17

How to prevent an object from getting garbage collected?

Are there any approaches by finalize or phantom reference or any other approaches?

I was asked this

相关标签:
11条回答
  • 2020-12-02 13:54

    The best way is to use Unsafe, although ByteBuffer might be a possible workaround for some cases.

    Also search for the keyword "off-heap" memory.

    Unsafe

    Advantages over ByteBuffer:

    • allows objects to be represented directly, without for serialization and thus faster
    • no bounds checking, so faster
    • explicit deallocation control
    • can allocate more than the JVM limit

    It is not however easy to get working. The method is described in the following articles:

    • http://mishadoff.com/blog/java-magic-part-4-sun-dot-misc-dot-unsafe/
    • https://highlyscalable.wordpress.com/2012/02/02/direct-memory-access-in-java/
    • http://java.dzone.com/articles/understanding-sunmiscunsafe

    They all consist of the following steps:

    • we need a sizeof operator, which Unsafe does not have. How to make one was asked at: In Java, what is the best way to determine the size of an object?. The best options is likely the instrument API, but that requires you to create a Jar and use special command line options...

    • once we have sizeof, allocate enough memory with Unsafe#allocateMemory, which is basically a malloc and returns an address

    • create a regular on heap object, copy it to the allocated memory with Unsafe#copyMemory. To do this, you need to the address of the on-heap object, and the size of the object

    • set an Object to point to the allocated memory, then cast the Object to your class.

      It does not seem possible to set the address of a variable directly with Unsafe, so we need to wrap the object into an array or wrapper object, and use Unsafe#arrayBaseOffset or Unsafe#objectFieldOffset.

    • once you are done, free the allocated memory with freeMemory

    If I ever get this to not segfault I will post an example :-)

    ByteBuffer

    Advantages over Unsafe:

    • stable across Java versions while Unsafe may break
    • does bound checking, so safer than... Unsafe, which allows for memory leaks and SIGSEGV

    JLS says:

    The contents of direct buffers may reside outside of the normal garbage-collected heap.

    Example of usage with primitives:

    ByteBuffer bb = ByteBuffer.allocateDirect(8);
    
    bb.putInt(0, 1);
    bb.putInt(4, 2);
    assert bb.getInt(0) == 1;
    assert bb.getInt(4) == 2;
    
    // Bound chekcs are done.
    boolean fail = false;
    try {
        bb.getInt(8);
    } catch(IndexOutOfBoundsException e) {
        fail = true;
    }
    assert fail;
    

    Related threads:

    • Difference between "on-heap" and "off-heap"
    0 讨论(0)
  • 2020-12-02 13:54

    There are 3 ways to prevent an Object from Garbage Collection as following:-

    1. Increase the Heap Size of JVM

      // Xms specifies initial memory to be allocated
      // and Xmx specifies maximum memory can be allocated
      java -Xms1024m -Xmx4096m ClassFile
      
    2. Use a SingleTon Class Object as @Tobias mentioned

      public class MySingletonClass {
           private static MySingletonClass uniqueInstance;
      
           // marking constructor as private
           private MySingletonClass() {
           }
      
           public static synchronized MySingletonClass getInstance() {
              if (uniqueInstance == null) {
                  uniqueInstance = new Singleton();
              }
              return uniqInstance;
          }
      }
      
    3. We can override finalize method. That is last method executed on an object. Hence, it will remain in memory.

      // using finalize method 
      class MyClassNotGc{ 
      
          static MyClassNotGc staticSelfObj; 
      
          pubic void finalize() { 
              // Putting the reference id 
              //Object reference saved. 
              //The object won't be collected by the garbage collector
              staticSelfObj = this; 
          } 
      
      }
      
    0 讨论(0)
  • 2020-12-02 13:56

    This sounds like one of those interview-only-time-you'll-see-it questions. finalize() is run when your object is getting garbage collected, so it'd be pretty perverse to put something in there to prevent collection. Normally you just hold a reference and that's all you need.

    I'm not even sure what would happen if you'd create a new reference for something in the finalizer - since the garbage collector's already decided to collect it would you then end up with a null ref? Seems like a poor idea, in any case. e.g.

    public class Foo {
       static Foo reference;
      ...
      finalize (){ 
         reference = this; 
      }
    }
    

    I doubt this would work, or it might work but be dependant on the GC implenetation, or be "unspecified behavior". Looks evil, though.

    0 讨论(0)
  • 2020-12-02 14:03

    I believe there is a pattern out there for this. Not sure if it the factory pattern. But you have one object that creates all your objects and holds a reference to them. When you are finished with them, you de-reference them in the factory, making the call explicit.

    0 讨论(0)
  • 2020-12-02 14:11

    The trick answer your interviewer was looking for is probably that he wants you to know that you can prevent garbage collection from removing an object by forcing a memory leak.

    Obviously, if you keep a reference to the object in some long-lived context, it won't be collected, but that's not what the OP's recruiter asked about. That's not something which happens in the finalize method.

    What you can do to prevent garbage collection from within the finalize method is to write an infinite loop, in which you call Thread.yield();(presumably to keep an empty loop from being optimized away):

    @Override
    protected void finalize() throws Throwable { 
        while (true) { 
            Thread.yield(); 
        } 
    } 
    

    My reference here is an article by Elliot Back, in which describes forcing a memory leak by this method.

    Just another way in which finalize methods are evil.

    0 讨论(0)
提交回复
热议问题