精华内容
下载资源
问答
  • finalizer

    2008-12-08 16:53:00
    finalizer 子类如果覆盖了父类的finalizer,子类应该手工调用父类的finalizer,应该放在finally里,以确保子类finalize时出异常时,父类finalizer仍被调用利用匿名类,终结外围实体(enclosing ...
    子类如果覆盖了父类的finalizer,子类应该手工调用父类的finalizer,应该放在finally里,以确保子类finalize时出异常时,父类finalizer仍被调用

    利用匿名类,终结外围实体(enclosing instance),外围实体在一个private instance中存储一个reference,指向终结函数守卫者(finalizer guardian),于是,finalizer guardian在外部实体存在时也存在,当guardian被终结时,它执行外围实体所期望的终结动作。

    public class Foo{

    private final object finalizerGuardian = new Object(){

           protected void finalize() throws Throwable{

                  //终结外围实体

    }

    }

    }
    posted on 2008-12-08 16:53 feixingfei 阅读(...) 评论(...) 编辑 收藏

    转载于:https://www.cnblogs.com/feixingfei/archive/2008/12/08/2297665.html

    展开全文
  • Valid finalizer

    2021-01-06 01:43:03
    Or Finalizer thread becomes broken after a few calls to ~PyObject. ... <h3>Checklist <p>Check all those that are applicable and complete. <ul><li>[ ] Make sure to include one or more tests for your ...
  • <div><p>After adding new finalizer (V2 Finalizer), update finalizer upgrade tests to validate against either of v1 or v2 finalizers.</p><p>该提问来源于开源项目:kubernetes/ingress-gce</p></div>
  • 前一阵排查一个跟java的finalizer有关的问题,发现网上虽然有很多关于finalizer的描述,但是大多都语焉不详,草草说了几句“带finalize的对象会进入finalizer队列”然后就没下文了,这让我研究了很久也没搞明白这个...

    1.摘要

    前一阵排查一个跟java的finalizer有关的问题,发现网上虽然有很多关于finalizer的描述,但是大多都语焉不详,草草说了几句“带finalize的对象会进入finalizer队列”然后就没下文了,这让我研究了很久也没搞明白这个finalizer队列究竟是什么原理,也没明白为什么heap里面的Finalizer对象非常多但是用jmap -finalizerinfo的时候总是显示为0,最后只好看jdk源代码解释这个问题。代码基于openjdk6。

    2.finalize()和Finalizer的创建

    首先,如果某个类Override了finalze方法的话,parse这个class时会把_has_finalizer置为TRUE。

    share/vm/classfile/classFileParser.cpp

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    methodHandle ClassFileParser::parse_method(constantPoolHandle cp, bool is_interface,

                                               AccessFlags *promoted_flags,

                                               typeArrayHandle* method_annotations,

                                               typeArrayHandle* method_parameter_annotations,

                                               typeArrayHandle* method_default_annotations,

                                               TRAPS) {

    ......                                          

      if (name == vmSymbols::finalize_method_name() &&

          signature == vmSymbols::void_method_signature()) {

        if (m->is_empty_method()) {

          _has_empty_finalizer = true;

        } else {

          _has_finalizer = true;

        }

      }

    .......

    }  

    在创建对象时,会在has_finalizer=true时调用register_finalizer。 share/vm/oops/instanceKlass.cpp

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    instanceOop instanceKlass::allocate_instance(TRAPS) {

      assert(!oop_is_instanceMirror(), "wrong allocation path");

      bool has_finalizer_flag = has_finalizer(); // Query before possible GC

      int size = size_helper();  // Query before forming handle.

     

      KlassHandle h_k(THREAD, as_klassOop());

     

      instanceOop i;

     

      i = (instanceOop)CollectedHeap::obj_allocate(h_k, size, CHECK_NULL);

      if (has_finalizer_flag && !RegisterFinalizersAtInit) {

        i = register_finalizer(i, CHECK_NULL);

      }

      return i;

    }

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    instanceOop instanceKlass::register_finalizer(instanceOop i, TRAPS) {

      if (TraceFinalizerRegistration) {

        tty->print("Registered ");

        i->print_value_on(tty);

        tty->print_cr(" (" INTPTR_FORMAT ") as finalizable", (address)i);

      }

      instanceHandle h_i(THREAD, i);

      // Pass the handle as argument, JavaCalls::call expects oop as jobjects

      JavaValue result(T_VOID);

      JavaCallArguments args(h_i);

      methodHandle mh (THREAD, Universe::finalizer_register_method());

      JavaCalls::call(&result, mh, &args, CHECK_NULL);

      return h_i();

    }

     

    在register_finalizer里调用了finalizer_register_method,这个method指向Finalizer类的register方法:

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    final class Finalizer extends FinalReference {

        private static ReferenceQueue queue = new ReferenceQueue();

        

        private static Finalizer unfinalized = null;

        

        private Finalizer

            next = null,

            prev = null;

            

        private Finalizer(Object finalizee) {

            super(finalizee, queue);

            add();

        }

        

        private void add() {

            synchronized (lock) {

                if (unfinalized != null) {

                    this.next = unfinalized;

                    unfinalized.prev = this;

                }

                unfinalized = this;

            }

        }

        

        /* Invoked by VM */

        static void register(Object finalizee) {

            new Finalizer(finalizee);

        }

    }

     

    Finalizer对象用next和prev指针维护了双向链表,unfinalilzed变量实际是链表的表尾,并声明了一个静态变量queue,可以看到在构造函数里调用了父类的构造函数和add()

    FinalReference也调用了父类的构造函数

     

     

    1

    2

    3

    4

    5

    class FinalReference<T> extends Reference<T> {

        public FinalReference(T referent, ReferenceQueue<? super T> q) {

            super(referent, q);

        }

    }

     

    Reference类里有一个本地成员变量queue,调用构造函数时这个变量被赋值为Finalizer的静态queue。

     

     

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    public abstract class Reference<T> {

        ReferenceQueue<? super T> queue;

        Reference(T referent, ReferenceQueue

     

     

     

    <? super T> queue) {

            this.referent = referent;

            this.queue = (queue == null) ? ReferenceQueue.NULL : queue;

        }

    }

     

    到这里可以小结一下: 1. 在创建对象时,如果对象override了finalize()方法,jvm会同时创建一个Finalizer对象 2. 所有Finalizer对象组成了一个双向链表 3. 所有Finalizer对象都有一个名为queue的成员变量,指向的都是Finalizer类的静态Queue。

    3.Finalizer的销毁和Finalizer Queue

    那么再看一下这些变量和queue有什么用,由于线上是old区cms回收的问题,这里就以cms为例:

    先从cms回收器的入口开始,默认的cms回收器是由一个后台的thread执行的,只挑重点。 share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.cpp

     

     

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    void ConcurrentMarkSweepThread::run() {

    .......

     

      while (!_should_terminate) {

        sleepBeforeNextCycle();

        if (_should_terminate) break;

        _collector->collect_in_background(false);  // !clear_all_soft_refs

      }

    ......

    }

     

    这里调用到了CMSCollector的collect_in_background函数: share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp

     

     

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    32

    33

    34

    35

    36

    37

    38

    39

    40

    41

    42

    void CMSCollector::collect_in_background(bool clear_all_soft_refs) {

    .......

        switch (_collectorState) {

          case InitialMarking:

            ...

            break;

          case Marking:

            ...

            break;

          case Precleaning:

            ...

            break;

          case AbortablePreclean:

            ...

            break;

          case FinalMarking:

            {

              ReleaseForegroundGC x(this);

     

              VM_CMS_Final_Remark final_remark_op(this);

              VMThread::execute(&final_remark_op);

            }

            assert(_foregroundGCShouldWait, "block post-condition");

            break;

          case Sweeping:

            ...

          case Resetting:

            // CMS heap resizing has been completed

            reset(true);

            assert(_collectorState == Idling, "Collector state should "

              "have changed");

            stats().record_cms_end();

            // Don't move the concurrent_phases_end() and compute_new_size()

            // calls to here because a preempted background collection

            // has it's state set to "Resetting".

            break;

          case Idling:

          default:

            ShouldNotReachHere();

            break;

        }

    }

     

    在FinalMarking里执行了final_remark_op

    share/vm/gc_implementation/concurrentMarkSweep/vmCMSOperations.cpp

     

     

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    void VM_CMS_Final_Remark::doit() {

    .....

      VM_CMS_Operation::verify_before_gc();

     

      IsGCActiveMark x; // stop-world GC active

      _collector->do_CMS_operation(CMSCollector::CMS_op_checkpointRootsFinal);

     

      VM_CMS_Operation::verify_after_gc();

    ......

    }

     

    真正的执行逻辑在do_CMS_operation:

     

     

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    void CMSCollector::do_CMS_operation(CMS_op_type op) {

      gclog_or_tty->date_stamp(PrintGC && PrintGCDateStamps);

      TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty);

      TraceTime t("GC", PrintGC, !PrintGCDetails, gclog_or_tty);

      TraceCollectorStats tcs(counters());

     

      switch (op) {

        case CMS_op_checkpointRootsInitial: {

          SvcGCMarker sgcm(SvcGCMarker::OTHER);

          checkpointRootsInitial(true);       // asynch

          if (PrintGC) {

            _cmsGen->printOccupancy("initial-mark");

          }

          break;

        }

        case CMS_op_checkpointRootsFinal: {

          SvcGCMarker sgcm(SvcGCMarker::OTHER);

          checkpointRootsFinal(true,    // asynch

                               false,   // !clear_all_soft_refs

                               false);  // !init_mark_was_synchronous

          if (PrintGC) {

            _cmsGen->printOccupancy("remark");

          }

          break;

        }

        default:

          fatal("No such CMS_op");

      }

    }

     

    调用了checkpointRootsFinal,之后一路徘徊到ReferenceProcessor的enqueue_discovered_references:

     

     

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    32

    33

    34

    35

    36

    37

    38

    39

    40

    41

    42

    void CMSCollector::checkpointRootsFinal(bool asynch,

      bool clear_all_soft_refs, bool init_mark_was_synchronous) {

    .....

      if (asynch) {

      ......

        checkpointRootsFinalWork(asynch, clear_all_soft_refs, false);

      } else {

        // already have all the locks

        checkpointRootsFinalWork(asynch, clear_all_soft_refs,

                                 init_mark_was_synchronous);

      }

    ......

    }

     

    void CMSCollector::checkpointRootsFinalWork(bool asynch,

      bool clear_all_soft_refs, bool init_mark_was_synchronous) {

    .......

      {

        NOT_PRODUCT(TraceTime ts("refProcessingWork", PrintGCDetails, false, gclog_or_tty);)

        refProcessingWork(asynch, clear_all_soft_refs);

      }

      verify_work_stacks_empty();

      verify_overflow_empty();

     

      if (should_unload_classes()) {

        CodeCache::gc_epilogue();

      }

    ......

    }

     

     

    void CMSCollector::refProcessingWork(bool asynch, bool clear_all_soft_refs) {

    ......

    if (rp->processing_is_mt()) {

        rp->balance_all_queues();

        CMSRefProcTaskExecutor task_executor(*this);

        rp->enqueue_discovered_references(&task_executor);

      } else {

        rp->enqueue_discovered_references(NULL);

      }  

    ......

    }

     

    在referenceProcessor里又是一顿调用:

    share/vm/memory/referenceProcessor.cpp

     

     

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    32

    33

    bool ReferenceProcessor::enqueue_discovered_references(AbstractRefProcTaskExecutor* task_executor) {

      NOT_PRODUCT(verify_ok_to_handle_reflists());

      if (UseCompressedOops) {

        return enqueue_discovered_ref_helper<narrowOop>(this, task_executor);

      } else {

        return enqueue_discovered_ref_helper<oop>(this, task_executor);

      }

    }

     

    template <class T>

    bool enqueue_discovered_ref_helper(ReferenceProcessor* ref,

                                       AbstractRefProcTaskExecutor* task_executor) {

    .......

      ref->enqueue_discovered_reflists((HeapWord*)pending_list_addr, task_executor);

    .......

    }

     

    void ReferenceProcessor::enqueue_discovered_reflists(HeapWord* pending_list_addr,

      AbstractRefProcTaskExecutor* task_executor) {

      if (_processing_is_mt && task_executor != NULL) {

        // Parallel code

        RefProcEnqueueTask tsk(*this, _discovered_refs,

                               pending_list_addr, _max_num_q);

        task_executor->execute(tsk);

      } else {

        // Serial code: call the parent class's implementation

        for (uint i = 0; i < _max_num_q * number_of_subclasses_of_ref(); i++) {

          enqueue_discovered_reflist(_discovered_refs[i], pending_list_addr);

          _discovered_refs[i].set_head(NULL);

          _discovered_refs[i].set_length(0);

        }

      }

    }

     

    在enqueue_discovered_reflists里引用的_discovered_refs类似邻接表,数组中每个元素指向一个链表,链表中每个节点是一个需要被回收掉的对象。
    最后会来到这个函数:

     

     

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    32

    33

    34

    35

    void ReferenceProcessor::enqueue_discovered_reflist(DiscoveredList& refs_list,

                                                        HeapWord* pending_list_addr) {

    .....    

        oop obj = NULL;

        oop next_d = refs_list.head();                                          

        while (obj != next_d) {

          obj = next_d;

          assert(obj->is_instanceRef(), "should be reference object");

          next_d = java_lang_ref_Reference::discovered(obj);

          if (TraceReferenceGC && PrintGCDetails) {

            gclog_or_tty->print_cr("        obj " INTPTR_FORMAT "/next_d " INTPTR_FORMAT,

                                   obj, next_d);

          }

          assert(java_lang_ref_Reference::next(obj) == NULL,

                 "The reference should not be enqueued");

          if (next_d == obj) {  // obj is last

            // Swap refs_list into pendling_list_addr and

            // set obj's next to what we read from pending_list_addr.

            oop old = oopDesc::atomic_exchange_oop(refs_list.head(), pending_list_addr);

            // Need oop_check on pending_list_addr above;

            // see special oop-check code at the end of

            // enqueue_discovered_reflists() further below.

            if (old == NULL) {

              // obj should be made to point to itself, since

              // pending list was empty.

              java_lang_ref_Reference::set_next(obj, obj);

            } else {

              java_lang_ref_Reference::set_next(obj, old);

            }

          } else {

            java_lang_ref_Reference::set_next(obj, next_d);

          }

          java_lang_ref_Reference::set_discovered(obj, (oop) NULL);

        }

    .....

     

    enqueue_discovered_reflist函数把所有节点的next指向自己,并把节点插入到pending_list_add的位置,这个pending_list_addr是jvm硬编码写死的,定义在:

    share/vm/classfile/javaClasses.cpp

     

     

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    void JavaClasses::compute_hard_coded_offsets() {

      const int x = heapOopSize;

      java_lang_ref_Reference::static_pending_offset = java_lang_ref_Reference::hc_static_pending_offset * x; //hc_static_pending_offset=1

    }

     

    HeapWord *java_lang_ref_Reference::pending_list_addr() {

      instanceKlass* ik = instanceKlass::cast(SystemDictionary::Reference_klass());

      address addr = ik->static_field_addr(static_pending_offset);

      // XXX This might not be HeapWord aligned, almost rather be char *.

      return (HeapWord*)addr;

    }

     

    查看java.lang.ref.Reference类也找到了这个定义:

     

     

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    public abstract class Reference<T> {

        private T referent;         /* Treated specially by GC */

        ReferenceQueue<? super T> queue;

        Reference next;

        transient private Reference<T> discovered;  /* used by VM */

        static private class Lock { };

        private static Lock lock = new Lock();

     

        /* List of References waiting to be enqueued.  The collector adds

         * References to this list, while the Reference-handler thread removes

         * them.  This list is protected by the above lock object.

         */

        private static Reference pending = null;

    }

     

    在Reference内部启动了一个线程,用来处理这个pending list:

     

     

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    32

    33

    34

    35

    private static class ReferenceHandler extends Thread {

     

            ReferenceHandler(ThreadGroup g, String name) {

                super(g, name);

            }

     

            public void run() {

                for (;;) {

     

                    Reference r;

                    synchronized (lock) {

                        if (pending != null) {

                            r = pending;

                            Reference rn = r.next;

                            pending = (rn == r) ? null : rn;

                            r.next = r;

                        } else {

                            try {

                                lock.wait();

                            } catch (InterruptedException x) { }

                            continue;

                        }

                    }

     

                    // Fast path for cleaners

                    if (r instanceof Cleaner) {

                        ((Cleaner)r).clean();

                        continue;

                    }

     

                    ReferenceQueue q = r.queue;

                    if (q != ReferenceQueue.NULL) q.enqueue(r);

                }

            }

        }

     

    并且这个线程的级别是最高的:

     

     

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    static {

            ThreadGroup tg = Thread.currentThread().getThreadGroup();

            for (ThreadGroup tgn = tg;

                 tgn != null;

                 tg = tgn, tgn = tg.getParent());

            Thread handler = new ReferenceHandler(tg, "Reference Handler");

            /* If there were a special system-only priority greater than

             * MAX_PRIORITY, it would be used here

             */

            handler.setPriority(Thread.MAX_PRIORITY);

            handler.setDaemon(true);

            handler.start();

        }

     

    线程会把pending对象所指的reference移出链表,如果对象的queue不是空,则把对象放到queue中。对于finalizer对象来说,这个queue是之前提到的finalizer类的静态变量queue,在Finailzer类中也有一个对应的处理线程:

     

     

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    private static class FinalizerThread extends Thread {

            private volatile boolean running;

            FinalizerThread(ThreadGroup g) {

                super(g, "Finalizer");

            }

            public void run() {

                if (running)

                    return;

                running = true;

                for (;;) {

                    try {

                        Finalizer f = (Finalizer)queue.remove();

                        f.runFinalizer();

                    } catch (InterruptedException x) {

                        continue;

                    }

                }

            }

        }

     

    4.总结

    最后总结一下finalizer的生存周期:

    1. 在创建对象时,如果对象override了finalize()方法,jvm会同时创建一个Finalizer对象
    2. 所有Finalizer对象组成了一个双向链表
    3. 所有Finalizer对象都有一个名为queue的成员变量,指向的都是Finalizer类的静态Queue。
    4. cms gc执行到mark阶段的最后时,会把需要gc的对象加入到Reference的pending list中。
    5. 有一个专门的高级别线程Reference Handler处理pending list,把pending list中的对象取出来,放到这个对象所指的Reference Queue中,对于Finalizer对象来说,这个queue指向Finalizer类的静态Queue。
    6. Finalizer类有一个专门的线程负责从queue中取对象,并且执行finalizer引用的对象的finalize函数。

    jvm的代码还是非常复杂的,感觉这次看的还是太粗略,会有不少疏漏,过段时间得抽空完整的了解一下jvm源代码。

    展开全文
  • Finalizer not called

    2021-01-12 01:19:58
    - if the called javascript function does nothing, then the finalizer is called at the end of the function call. <pre><code>javascript function func(array) { } </code></pre> <ul><li>if the called ...
  • Fiber finalizer fix

    2021-01-09 05:49:51
    s finalizer was triggering the creation of a new ThreadFiber instance. So, for every ThreadFiber instance that got garbage collected another one was created. <p>This behavior can lead to the finalizer...
  • EventType Finalizer

    2020-11-23 04:56:53
    <ul><li>Replace the existing EventType owns Feed logic with a finalizer for EventTypes.<ul><li>This allows Feeds to use the standard garbage collector, getting deleted when its owning Flow is deleted....
  • add pingsource finalizer

    2020-11-24 17:59:52
    <h2>- Add finalizer to ensure internal cache is properly updated. <p>- <p><strong>Release Note</strong></p> <pre><code>release-note </code></pre> <p><strong>Docs</strong></p> 该提问来源于开源...
  • Finalizer throws exception

    2020-12-08 21:02:00
    <p>System.InvalidOperationException: The LightningEnvironment was not disposed and cannot be reliably dealt with from the finalizer at LightningDB.LightningEnvironment.Dispose (System.Boolean ...
  • <div><p>Currently a finalizer may run twice in special cases even when the object is not rescued. Make the guarantees exact: - If an object is not rescued, its finalizer is executed once. - If an ...
  • unify finalizer handling

    2021-01-01 06:52:12
    This PR unifies the finalizer handling across all controllers. Instead of doing: <pre><code>golang set := strings.NewSet(obj.Finalizers...) set.Insert("myFancyFinalizer") obj.Finalizers &#...
  • <div><p>So, remembering how the finalizer torture test had to take pains to avoid generating new refzero entries, I realized this can be an issue in Ecmascript code as well, and came up with this ...
  • Mat Finalizer Missing?

    2021-01-07 11:57:01
    <p>I assumed that there was a finalizer in place for garbage collection to call Dispose() if the matrix went out of scope. However, it doesn't seem to be the case, and I don't see a ~Mat ...
  • s nothing to remove the finalizer. Then we are stuck with a namespace that can't be easily deleted. Removing this for now since this is more of a nice to have than essential feature. </p><p>该...
  • <p>In NetworkSender base class there is an finalizer that does nothing. This is causing a lot of objects being placed on finalizer queue thus making the unnecessary waste of memory. Such objects are ...
  • 转自http://ju.outofmemory.cn/entry/74671本文介绍的是Java里一个内建的概念,Finalizer。你可能对它对数家珍,但也可能从未听闻过,这得看你有没有花时间完整地看过一遍java.lang.Object类了。在java.lang.Object...

    转自 http://ju.outofmemory.cn/entry/74671

    本文介绍的是Java里一个内建的概念,Finalizer。你可能对它对数家珍,但也可能从未听闻过,这得看你有没有花时间完整地看过一遍java.lang.Object类了。在java.lang.Object里面就有一个finalize()的方法。这个方法的实现是空的,不过一旦实现了这个方法,就会触发JVM的内部行为,威力和危险并存。

    如果JVM发现某个类实现了finalize()方法的话,那么见证奇迹的时刻到了。我们先来创建一个实现了这个非凡的finalize()方法的类,然后看下这种情况下JVM的处理会有什么不同。我们先从一个简单的示例程序开始:

    importjava.util.concurrent.atomic.AtomicInteger;classFinalizable{staticAtomicIntegeraliveCount =newAtomicInteger(0);Finalizable(){aliveCount.incrementAndGet();}@Overrideprotectedvoidfinalize()throwsThrowable{Finalizable.aliveCount.decrementAndGet();}publicstaticvoidmain(Stringargs[]){for(inti =0;;i++){Finalizablef =newFinalizable();if((i %100_000)==0){System.out.format("After creating %d objects, %d are still alive.%n",newObject[]{i,Finalizable.aliveCount.get()});}}}}

    这个程序使用了一个无限循环来创建对象。它同时还用了一个静态变量aliveCount来跟踪一共创建了多少个实例。每创建了一个新对象,计数器会加1,一旦GC完成后调用了finalize()方法,计数器会跟着减1。

    你觉得这小段代码的输出结果会是怎样的呢?由于新创建的对象很快就没人引用了,它们马上就可以被GC回收掉。因此你可能会认为这段程序可以不停的运行下去,:

    Aftercreating 345,000,000objects,0are still alive.Aftercreating 345,100,000objects,0are still alive.Aftercreating 345,200,000objects,0are still alive.Aftercreating 345,300,000objects,0are still alive.

    显然结果并非如此。现实的结果完全不同,在我的Mac OS X的JDK 1.7.0_51上,程序大概在创建了120万个对象后就抛出java.lang.OutOfMemoryError: GC overhead limitt exceeded异常退出了。

    Aftercreating 900,000objects,791,361are still alive.Aftercreating 1,000,000objects,875,624are still alive.Aftercreating 1,100,000objects,959,024are still alive.Aftercreating 1,200,000objects,1,040,909are still alive.Exceptioninthread "main"java.lang.OutOfMemoryError:GC overhead limit exceeded at java.lang.ref.Finalizer.register(Finalizer.java:90)at java.lang.Object.(Object.java:37)at eu.plumbr.demo.Finalizable.(Finalizable.java:8)at eu.plumbr.demo.Finalizable.main(Finalizable.java:19)

    垃圾回收的行为

    想弄清楚到底发生了什么,你得看下这段程序在运行时的状况如何。我们来打开-XX:+PrintGCDetails选项再运行一次看看:

    [GC [PSYoungGen:16896K->2544K(19456K)]16896K->16832K(62976K),0.0857640secs][Times:user=0.22sys=0.02,real=0.09secs][GC [PSYoungGen:19440K->2560K(19456K)]33728K->31392K(62976K),0.0489700secs][Times:user=0.14sys=0.01,real=0.05secs][GC--[PSYoungGen:19456K->19456K(19456K)]48288K->62976K(62976K),0.0601190secs][Times:user=0.16sys=0.01,real=0.06secs][FullGC [PSYoungGen:16896K->14845K(19456K)][ParOldGen:43182K->43363K(43520K)]60078K->58209K(62976K)[PSPermGen:2567K->2567K(21504K)],0.4954480secs][Times:user=1.76sys=0.01,real=0.50secs][FullGC [PSYoungGen:16896K->16820K(19456K)][ParOldGen:43361K->43361K(43520K)]60257K->60181K(62976K)[PSPermGen:2567K->2567K(21504K)],0.1379550secs][Times:user=0.47sys

    展开全文
  • kubernetes-finalizer

    2020-09-27 18:11:01
    finalizer介绍 介绍1: Finalizers 允许 Operator 控制器实现异步的 pre-delete hook。比如你给 API 类型中的每个对象都创建了对应的外部资源,你希望在 k8s 删除对应资源时同时删除关联的外部资源,那么可以通过 ...

    finalizer介绍

    介绍1:
    Finalizers 允许 Operator 控制器实现异步的 pre-delete hook。比如你给 API 类型中的每个对象都创建了对应的外部资源,你希望在 k8s 删除对应资源时同时删除关联的外部资源,那么可以通过 Finalizers 来实现。

    Finalizers 是由字符串组成的列表,当 Finalizers 字段存在时,相关资源不允许被强制删除。存在 Finalizers 字段的的资源对象接收的第一个删除请求设置 metadata.deletionTimestamp 字段的值, 但不删除具体资源,在该字段设置后, finalizer 列表中的对象只能被删除,不能做其他操作。

    当 metadata.deletionTimestamp 字段非空时,controller watch 对象并执行对应 finalizers 的动作,当所有动作执行完后,需要清空 finalizers ,之后 k8s 会删除真正想要删除的资源。

    介绍2:
    k8s资源中ObjectMeta.DeletionTimestamp 和 DemoMicroService.ObjectMeta.Finalizers 这两个元信息。前者表示删除该资源的这一行为的具体发生时间,如果不为0则表示删除资源的指令已经下达;而后者表示在真正删除 资源之前,,还有哪些逻辑没有被执行,如果 Finalizers 不为空,那么该资源则不会真正消失。

    举个栗子:
    有时候我们再删除某个资源时,该资源一直处于Terminating状态,即使加上了–force --grance-period=0之后仍然删不掉,这时可以去edit该资源文件,将finalizer配置项置为空,即可删除。

    operator中finalizer使用

    此处引用阿里云的部分代码做一个介绍。
    git地址:https://github.com/l4wei/kubebuilder-example/

    dms为自定义的crd资源。
    finalizer为字符串常量。
    demoMicroServiceFinalizer string = “demomicroservice.finalizers.devops.my.domain”
    在这里插入图片描述
    61行 先判断删除指令有没有下发,如果为空则没有,需要确保该资源的finalizer值不为空,然后更新该资源。

    75行 删除不为空,则代表删除指令已经下发,判断finalizer值已经清空了,则删掉在cleanDeployment方法中删除关联的资源,如果没有删除,则执行清空的finalizer的操作。

    展开全文
  • Finalizer attack

    2014-04-17 09:22:21
    Finalizer攻击: 在构造函数中抛出异常,目的是创建对象失败时当对象抛出异常后,对象会被垃圾清理器回收。而当垃圾清理器准备释放对象的内存时,它首先调用finalize方法,然后再回收内存。Finalizer攻击就是重载...
  • Add an event finalizer

    2020-11-20 18:37:13
    <div><p>This adds an <code>event_finalizer</code> hook that will be called after all subscribers have been notified of an event. This lets us record a completely successful event, while allowing ...
  • Document “finalizer

    2021-01-05 12:25:33
    - Add a glossary entry for <em>finalizer - and/or improve https://kubernetes.io/docs/concepts/workloads/controllers/garbage-collection/ to have a section specifically that explains what a finalizer is...
  • <div><p>Currently finalizer functions are not supported within clasp. This is a roadblock that prevents Clasp from being used with major libraries and applications. Finalizers provide a way to run a ...
  • add command to Finalizer

    2020-12-08 22:41:32
    Adds global Command (not specific to Yarn on NPM) to Finalizer. </li><li> <p>An explanation of the use cases your change solves </li></ul> <h1>98 <ul><li> [ ] I have viewed signed and have submitted ...
  • finalizer 在与主题直接合作或花时间学习它们之后,我经常会发现自己在网上注意到更多主题。 最近的Stephen Connolly ( CloudBees )发表了FileInputStream / FileOutputStream被认为有害的文章,引起了我的注意,...
  • <p>If you remove the finalizer, everything works fine. Tried it on my own profiler (www.getcodetrack.com), but also on Jetbrains Dottrace. Same result. In .NET 4.0 and 2.0 it works fine. <pre><code> ...
  • fix 4509, remove finalizer

    2020-12-08 18:59:39
    <ul><li>Do not use finalizer for IMC dispatcher</li></ul> <p><strong>Release Note</strong></p> <pre><code>release-note - :broom: Update or clean up current behavior Do not set the finalizer for ...
  • Blocked Finalizer Thread

    2016-12-15 17:14:48
    http://dotnetdebug.net/2005/06/22/blocked-finalizer-thread/ ...Blocked Finalizer Thread Posted by: Eran Sandler, in Managed Debugging, SOS, WinDbg Not all memory leaks in .NET applicatio
  • java Finalizer陷阱

    2019-04-19 10:52:15
    java Finalizer陷阱 java中使用可达性分析来确定对象是否需要回收,即使是不可达的对象,也不是“非死不可”的,这时候他们暂时处于“缓刑”阶段,要真正宣告一个对象死亡,至少要经历两次标记过程:如果对象在进行...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,095
精华内容 838
热门标签
关键字:

finalizer