Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  Main.java

  Sprache: JAVA
 

/*
 * Copyright (C) 2022 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


import java.lang.ref.PhantomReference;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.math.BigInteger;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.ConcurrentHashMap;
import java.util.TreeMap;

/**
 * Test that objects get finalized and their references cleared in the right order.
 *
 * We maintain a list of nominally MAX_LIVE_OBJS numbered finalizable objects.
 * We then alternately drop the last 50, and add 50 more. When we see an object finalized
 * or its reference cleared, we make sure that the preceding objects in its group of 50
 * have also had their references cleared. We also perform a number of other more
 * straightforward checks, such as ensuring that all references are eventually cleared,
 * and all objects are finalized.
 */

public class Main {
    // TODO(b/216481630) Enable CHECK_PHANTOM_REFS. This currently occasionally reports a few
    // PhantomReferences as not enqueued. If this report is correct, this needs to be tracked
    // down and fixed.
    static final boolean CHECK_PHANTOM_REFS = false;

    static final int MAX_LIVE_OBJS = 150;
    static final int DROP_OBJS = 50;  // Number of linked objects dropped in each batch.
    static final int MIN_LIVE_OBJS = MAX_LIVE_OBJS - DROP_OBJS;
    static final int TOTAL_OBJS = 200_000;  // Allocate this many finalizable objects in total.
    static final boolean REPORT_DROPS = false;
    static volatile boolean pleaseStop;

    AtomicInteger totalFinalized = new AtomicInteger(0);
    int maxDropped = 0;
    int liveObjects = 0;

    // Number of next finalizable object to be allocated.
    int nextAllocated = 0;

    // List of finalizable objects in descending order. We add to the front and drop
    // from the rear.
    FinalizableObject listHead;

    // A possibly incomplete list of FinalizableObject indices that were finalized, but
    // have yet to be checked for consistency with reference processing.
    ArrayBlockingQueue<Integer> finalized = new ArrayBlockingQueue<>(20_000);

    // Maps from object number to Reference; Cleared references are deleted when queues are
    // processed.
    TreeMap<Integer, MyWeakReference> weakRefs = new TreeMap<>();
    ConcurrentHashMap<Integer, MyPhantomReference> phantomRefs = new ConcurrentHashMap<>();

    class FinalizableObject {
        int n;
        FinalizableObject next;
        FinalizableObject(int num, FinalizableObject nextObj) {
            n = num;
            next = nextObj;
        }
        protected void finalize() {
            if (!inPhantomRefs(n)) {
                System.out.println("PhantomRef enqueued before finalizer ran");
            }
            totalFinalized.incrementAndGet();
            if (!finalized.offer(n) && REPORT_DROPS) {
                System.out.println("Dropped finalization of " + n);
            }
        }
    }
    ReferenceQueue<FinalizableObject> refQueue = new ReferenceQueue<>();
    class MyWeakReference extends WeakReference<FinalizableObject> {
        int n;
        MyWeakReference(FinalizableObject obj) {
            super(obj, refQueue);
            n = obj.n;
        }
    };
    class MyPhantomReference extends PhantomReference<FinalizableObject> {
        int n;
        MyPhantomReference(FinalizableObject obj) {
            super(obj, refQueue);
            n = obj.n;
        }
    }
    boolean inPhantomRefs(int n) {
        MyPhantomReference ref = phantomRefs.get(n);
        if (ref == null) {
            return false;
        }
        if (ref.n != n) {
            System.out.println("phantomRef retrieval failed");
        }
        return true;
    }

    void CheckOKToClearWeak(int num) {
        if (num > maxDropped) {
            System.out.println("WeakRef to live object " + num + " was cleared/enqueued.");
        }
        int batchEnd = (num / DROP_OBJS + 1) * DROP_OBJS;
        for (MyWeakReference wr : weakRefs.subMap(num + 1, batchEnd).values()) {
            if (wr.n <= num || wr.n / DROP_OBJS != num / DROP_OBJS) {
                throw new AssertionError("MyWeakReference logic error!");
            }
            // wr referent was dropped in same batch and precedes it in list.
            if (wr.get() != null) {
                // This violates the WeakReference spec, and can result in strong references
                // to objects that have been cleaned.
                System.out.println("WeakReference to " + wr.n
                    + " was erroneously cleared after " + num);
            }
        }
    }

    void CheckOKToClearPhantom(int num) {
        if (num > maxDropped) {
            System.out.println("PhantomRef to live object " + num + " was enqueued.");
        }
        MyWeakReference wr = weakRefs.get(num);
        if (wr != null && wr.get() != null) {
            System.out.println("PhantomRef cleared before WeakRef for " + num);
        }
    }

    void emptyAndCheckQueues() {
        // Check recently finalized objects for consistency with cleared references.
        while (true) {
            Integer num = finalized.poll();
            if (num == null) {
                break;
            }
            MyWeakReference wr = weakRefs.get(num);
            if (wr != null) {
                if (wr.n != num) {
                    System.out.println("Finalization logic error!");
                }
                if (wr.get() != null) {
                    System.out.println("Finalizing object with uncleared reference");
                }
            }
            CheckOKToClearWeak(num);
        }
        // Check recently enqueued references for consistency.
        while (true) {
            Reference<FinalizableObject> ref = (Reference<FinalizableObject>) refQueue.poll();
            if (ref == null) {
                break;
            }
            if (ref instanceof MyWeakReference) {
                MyWeakReference wr = (MyWeakReference) ref;
                if (wr.get() != null) {
                    System.out.println("WeakRef " + wr.n + " enqueued but not cleared");
                }
                CheckOKToClearWeak(wr.n);
                if (weakRefs.remove(Integer.valueOf(wr.n)) != ref) {
                    System.out.println("Missing WeakReference: " + wr.n);
                }
            } else if (ref instanceof MyPhantomReference) {
                MyPhantomReference pr = (MyPhantomReference) ref;
                CheckOKToClearPhantom(pr.n);
                if (phantomRefs.remove(Integer.valueOf(pr.n)) != ref) {
                    System.out.println("Missing PhantomReference: " + pr.n);
                }
            } else {
                System.out.println("Found unrecognized reference in queue");
            }
        }
    }


    /**
     * Add n objects to the head of the list. These will be assigned the next n consecutive
     * numbers after the current head of the list.
     */

    void addObjects(int n) {
        for (int i = 0; i < n; ++i) {
            int me = nextAllocated++;
            listHead = new FinalizableObject(me, listHead);
            weakRefs.put(me, new MyWeakReference(listHead));
            phantomRefs.put(me, new MyPhantomReference(listHead));
        }
        liveObjects += n;
    }

    /**
     * Drop n finalizable objects from the tail of the list. These are the lowest-numbered objects
     * in the list.
     */

    void dropObjects(int n) {
        FinalizableObject list = listHead;
        FinalizableObject last = null;
        if (n > liveObjects) {
            System.out.println("Removing too many elements");
        }
        if (liveObjects == n) {
            maxDropped = list.n;
            listHead = null;
        } else {
            final int skip = liveObjects - n;
            for (int i = 0; i < skip; ++i) {
                last = list;
                list = list.next;
            }
            int expected = nextAllocated - skip - 1;
            if (list.n != expected) {
                System.out.println("dropObjects found " + list.n + " but expected " + expected);
            }
            maxDropped = expected;
            last.next = null;
        }
        liveObjects -= n;
    }

    void testLoop() {
        System.out.println("Starting");
        addObjects(MIN_LIVE_OBJS);
        final int ITERS = (TOTAL_OBJS - MIN_LIVE_OBJS) / DROP_OBJS;
        for (int i = 0; i < ITERS; ++i) {
            addObjects(DROP_OBJS);
            if (liveObjects != MAX_LIVE_OBJS) {
                System.out.println("Unexpected live object count");
            }
            dropObjects(DROP_OBJS);
            if (i % 100 == 0) {
              // Make sure we don't fall too far behind, otherwise we may run out of memory.
              System.runFinalization();
            }
            emptyAndCheckQueues();
        }
        dropObjects(MIN_LIVE_OBJS);
        if (liveObjects != 0 || listHead != null) {
            System.out.println("Unexpected live objecs at end");
        }
        if (maxDropped != TOTAL_OBJS - 1) {
            System.out.println("Unexpected dropped object count: " + maxDropped);
        }
        for (int i = 0; i < 2; ++i) {
            Runtime.getRuntime().gc();
            System.runFinalization();
            emptyAndCheckQueues();
        }
        if (!weakRefs.isEmpty()) {
            System.out.println("Weak Reference map nonempty size = " + weakRefs.size());
        }
        if (CHECK_PHANTOM_REFS && !phantomRefs.isEmpty()) {
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                System.out.println("Unexpected interrupt");
            }
            if (!phantomRefs.isEmpty()) {
                System.out.println("Phantom Reference map nonempty size = " + phantomRefs.size());
                System.out.print("First elements:");
                int i = 0;
                for (MyPhantomReference pr : phantomRefs.values()) {
                    System.out.print(" " + pr.n);
                    if (++i > 10) {
                        break;
                    }
                }
                System.out.println("");
            }
        }
        if (totalFinalized.get() != TOTAL_OBJS) {
            System.out.println("Finalized only " + totalFinalized + " objects");
        }
    }

    static Runnable causeGCs = new Runnable() {
        public void run() {
            // Allocate a lot.
            BigInteger counter = BigInteger.ZERO;
            while (!pleaseStop) {
                counter = counter.add(BigInteger.TEN);
            }
            // Look at counter to reduce chance of optimizing out the allocation.
            if (counter.longValue() % 10 != 0) {
                 System.out.println("Bad causeGCs counter value: " + counter);
            }
        }
    };

    public static void main(String[] args) throws Exception {
        Main theTest = new Main();
        Thread gcThread = new Thread(causeGCs);
        gcThread.setDaemon(true);  // Terminate if main thread dies.
        gcThread.start();
        theTest.testLoop();
        pleaseStop = true;
        gcThread.join();
        System.out.println("Finished");
    }
}

Messung V0.5 in Prozent
C=90 H=95 G=92

¤ Dauer der Verarbeitung: 0.11 Sekunden  (vorverarbeitet am  2026-06-29) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik