Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Android/art/art/test/913-heaps/src/art/   (Android Betriebssystem Version 17©)  Datei vom 26.5.2026 mit Größe 25 kB image not shown  

Quelle  Test913.java

  Sprache: JAVA
 

/*
 * Copyright (C) 2016 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.
 */


package art;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.concurrent.CountDownLatch;

public class Test913 {
    public static void run() throws Exception {
        doTest();

        // Use a countdown latch for synchronization, as join() will introduce more roots.
        final CountDownLatch cdl1 = new CountDownLatch(1);

        // Run the follow-references tests on a dedicated thread so we know the specific
        // Thread type.
        Thread t = new Thread() {
            @Override
            public void run() {
                try {
                    Test913.runFollowReferences();
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
                cdl1.countDown();
            }
        };
        t.start();
        cdl1.await();

        doExtensionTests();
    }

    public static void runFollowReferences() throws Exception {
        new TestConfig().doFollowReferencesTest();

        Runtime.getRuntime().gc();
        Runtime.getRuntime().gc();

        new TestConfig(null01, -1).doFollowReferencesTest();

        Runtime.getRuntime().gc();
        Runtime.getRuntime().gc();

        new TestConfig(null0, Integer.MAX_VALUE, 1).doFollowReferencesTest();

        Runtime.getRuntime().gc();
        Runtime.getRuntime().gc();

        doStringTest();

        Runtime.getRuntime().gc();
        Runtime.getRuntime().gc();

        doPrimitiveArrayTest();
        doPrimitiveFieldTest();

        Runtime.getRuntime().gc();
        Runtime.getRuntime().gc();

        // Test klass filter.
        System.out.println("--- klass ---");
        new TestConfig(A.class0).doFollowReferencesTest();

        // Test heap filter.
        System.out.println("--- heap_filter ---");
        System.out.println("---- tagged objects");
        new TestConfig(null0x4).doFollowReferencesTest();
        System.out.println("---- untagged objects");
        new TestConfig(null0x8).doFollowReferencesTest();
        System.out.println("---- tagged classes");
        new TestConfig(null0x10).doFollowReferencesTest();
        System.out.println("---- untagged classes");
        new TestConfig(null0x20).doFollowReferencesTest();
    }

    public static void doTest() throws Exception {
        setupGcCallback();

        enableGcTracking(true);
        runGc();
        enableGcTracking(false);
    }

    public static void doStringTest() throws Exception {
        final String str = new String("HelloWorld");
        final String str2 = new String("");
        Object o = new Object() {
                String s = str;
                String s2 = str2;
        };

        setTag(str, 1);
        setTag(str2, 2);
        System.out.println(Arrays.toString(followReferencesString(o)));
        System.out.println(getTag(str));
        System.out.println(getTag(str2));
    }

    public static void doPrimitiveArrayTest() throws Exception {
        final boolean[] zArray = new boolean[] { falsetrue };
        setTag(zArray, 1);

        final byte[] bArray = new byte[] { 123 };
        setTag(bArray, 2);

        final char[] cArray = new char[] { 'A''Z' };
        setTag(cArray, 3);

        final short[] sArray = new short[] { 123 };
        setTag(sArray, 4);

        final int[] iArray = new int[] { 123 };
        setTag(iArray, 5);

        final float[] fArray = new float[] { 0.0f, 1.0f };
        setTag(fArray, 6);

        final long[] lArray = new long[] { 123 };
        setTag(lArray, 7);

        final double[] dArray = new double[] { 0.01.0 };
        setTag(dArray, 8);

        Object o = new Object() {
                Object z = zArray;
                Object b = bArray;
                Object c = cArray;
                Object s = sArray;
                Object i = iArray;
                Object f = fArray;
                Object l = lArray;
                Object d = dArray;
        };

        System.out.println(followReferencesPrimitiveArray(o));
        System.out.print(getTag(zArray));
        System.out.print(getTag(bArray));
        System.out.print(getTag(cArray));
        System.out.print(getTag(sArray));
        System.out.print(getTag(iArray));
        System.out.print(getTag(fArray));
        System.out.print(getTag(lArray));
        System.out.println(getTag(dArray));
    }

    public static void doPrimitiveFieldTest() throws Exception {
        // Force GCs to clean up dirt.
        Runtime.getRuntime().gc();
        Runtime.getRuntime().gc();

        doTestPrimitiveFieldsClasses();

        doTestPrimitiveFieldsIntegral();

        // Force GCs to clean up dirt.
        Runtime.getRuntime().gc();
        Runtime.getRuntime().gc();

        doTestPrimitiveFieldsFloat();

        // Force GCs to clean up dirt.
        Runtime.getRuntime().gc();
        Runtime.getRuntime().gc();
    }

    private static void doTestPrimitiveFieldsClasses() {
        setTag(IntObject.class10000);
        System.out.println(followReferencesPrimitiveFields(IntObject.class));
        System.out.println(getTag(IntObject.class));
        setTag(IntObject.class0);

        setTag(FloatObject.class10000);
        System.out.println(followReferencesPrimitiveFields(FloatObject.class));
        System.out.println(getTag(FloatObject.class));
        setTag(FloatObject.class0);

        boolean correctHeapValue = false;
        setTag(Inf1.class10000);
        String heapTrace = followReferencesPrimitiveFields(Inf1.class);

        if (!checkInitialized(Inf1.class)) {
            correctHeapValue = heapTrace.equals("10000@0 (static, int, index=0) 0000000000000000");
        } else {
            correctHeapValue = heapTrace.equals("10000@0 (static, int, index=0) 0000000000000001");
        }

        if (!correctHeapValue) {
            System.out.println("Heap Trace for Inf1 is not as expected:\n" + heapTrace);
        }

        System.out.println(getTag(Inf1.class));
        setTag(Inf1.class0);

        setTag(Inf2.class10000);
        heapTrace = followReferencesPrimitiveFields(Inf2.class);

        if (!checkInitialized(Inf2.class)) {
            correctHeapValue = heapTrace.equals("10000@0 (static, int, index=1) 0000000000000000");
        } else {
            correctHeapValue = heapTrace.equals("10000@0 (static, int, index=1) 0000000000000001");
        }

        if (!correctHeapValue)
            System.out.println("Heap Trace for Inf2 is not as expected:\n" + heapTrace);
        System.out.println(getTag(Inf2.class));
        setTag(Inf2.class0);
    }

    private static void doTestPrimitiveFieldsIntegral() {
        IntObject intObject = new IntObject();
        setTag(intObject, 10000);
        System.out.println(followReferencesPrimitiveFields(intObject));
        System.out.println(getTag(intObject));
    }

    private static void doTestPrimitiveFieldsFloat() {
        FloatObject floatObject = new FloatObject();
        setTag(floatObject, 10000);
        System.out.println(followReferencesPrimitiveFields(floatObject));
        System.out.println(getTag(floatObject));
    }

    static ArrayList<Object> extensionTestHolder;

    private static void doExtensionTests() {
        checkForExtensionApis();

        extensionTestHolder = new ArrayList<>();
        System.out.println();

        try {
            getHeapName(-1);
            System.out.println("Expected failure for -1");
        } catch (Exception e) {
        }
        System.out.println(getHeapName(0));
        System.out.println(getHeapName(1));
        System.out.println(getHeapName(2));
        System.out.println(getHeapName(3));
        try {
            getHeapName(4);
            System.out.println("Expected failure for -1");
        } catch (Exception e) {
        }

        System.out.println();

        setTag(Object.class100000);
        int objectClassHeapId = getObjectHeapId(100000);
        int objClassExpectedHeapId = hasImage() ? 1 : 3;
        if (objectClassHeapId != objClassExpectedHeapId) {
            throw new RuntimeException("Expected object class in heap " + objClassExpectedHeapId +
                    " but received " + objectClassHeapId);
        }

        A a = new A();
        extensionTestHolder.add(a);
        setTag(a, 100001);
        System.out.println(getObjectHeapId(100001));

        checkGetObjectHeapIdInCallback(100000, objClassExpectedHeapId);
        checkGetObjectHeapIdInCallback(1000013);

        long baseTag = 30000000;
        setTag(Object.class, baseTag + objClassExpectedHeapId);
        setTag(Class.class, baseTag + objClassExpectedHeapId);
        Object o = new Object();
        extensionTestHolder.add(o);
        setTag(o, baseTag + 3);

        iterateThroughHeapExt();

        extensionTestHolder = null;
    }

    private static void runGc() {
        clearStats();
        forceGarbageCollection();
        printStats();
    }

    private static void clearStats() {
        getGcStarts();
        getGcFinishes();
    }

    private static void printStats() {
        System.out.println("---");
        int s = getGcStarts();
        int f = getGcFinishes();
        System.out.println((s > 0) + " " + (f > 0));
    }

    private static boolean hasImage() {
        try {
            int pid = Integer.parseInt(new File("/proc/self").getCanonicalFile().getName());
            BufferedReader reader = new BufferedReader(new FileReader("/proc/" + pid + "/maps"));
            String line;
            while ((line = reader.readLine()) != null) {
                // On host the mappings end with .art and on device they end with .art]
                if (line.endsWith(".art]") || line.endsWith(".art")) {
                    reader.close();
                    return true;
                }
            }
            reader.close();
            return false;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private static class TestConfig {
        private Class<?> klass = null;
        private int heapFilter = 0;
        private int stopAfter = Integer.MAX_VALUE;
        private int followSet = -1;

        public TestConfig() {
        }
        public TestConfig(Class<?> klass, int heapFilter) {
            this.klass = klass;
            this.heapFilter = heapFilter;
        }
        public TestConfig(Class<?> klass, int heapFilter, int stopAfter, int followSet) {
            this.klass = klass;
            this.heapFilter = heapFilter;
            this.stopAfter = stopAfter;
            this.followSet = followSet;
        }

        public void doFollowReferencesTest() throws Exception {
            // Force GCs to clean up dirt.
            Runtime.getRuntime().gc();
            Runtime.getRuntime().gc();

            setTag(Thread.currentThread(), 3000);

            {
                ArrayList<Object> tmpStorage = new ArrayList<>();
                doFollowReferencesTestNonRoot(tmpStorage);
                tmpStorage = null;
            }

            // Force GCs to clean up dirt.
            Runtime.getRuntime().gc();
            Runtime.getRuntime().gc();

            doFollowReferencesTestRoot();

            // Force GCs to clean up dirt.
            Runtime.getRuntime().gc();
            Runtime.getRuntime().gc();
        }

        private void doFollowReferencesTestNonRoot(ArrayList<Object> tmpStorage) {
            Verifier v = new Verifier();
            tagClasses(v);
            A a = createTree(v);
            tmpStorage.add(a);
            v.add("0@0""1@1000");  // tmpStorage[0] --(array-element)--> a.

            doFollowReferencesTestImpl(null, stopAfter, followSet, null, v, null);
            doFollowReferencesTestImpl(a.foo2, stopAfter, followSet, null, v, "3@1001");

            tmpStorage.clear();
        }

        private void doFollowReferencesTestRoot() {
            Verifier v = new Verifier();
            tagClasses(v);
            A a = createTree(v);

            doFollowReferencesTestImpl(null, stopAfter, followSet, a, v, null);
            doFollowReferencesTestImpl(a.foo2, stopAfter, followSet, a, v, "3@1001");
        }

        private void doFollowReferencesTestImpl(A root, int stopAfter, int followSet,
                Object asRoot, Verifier v, String additionalEnabled) {
            String[] lines =
                    followReferences(heapFilter, klass, root, stopAfter, followSet, asRoot);

            v.process(lines, additionalEnabled, heapFilter != 0 || klass != null);
        }

        private static void tagClasses(Verifier v) {
            setTag(A.class1000);
            registerClass(1000, A.class);

            setTag(B.class1001);
            registerClass(1001, B.class);
            v.add("1001@0""1000@0");  // B.class --(superclass)--> A.class.

            setTag(C.class1002);
            registerClass(1002, C.class);
            v.add("1002@0""1001@0");  // C.class --(superclass)--> B.class.
            v.add("1002@0""2001@0");  // C.class --(interface)--> I2.class.

            setTag(I1.class2000);
            registerClass(2000, I1.class);

            setTag(I2.class2001);
            registerClass(2001, I2.class);
            v.add("2001@0""2000@0");  // I2.class --(interface)--> I1.class.
        }

        private static A createTree(Verifier v) {
            A aInst = new A();
            setTag(aInst, 1);
            String aInstStr = "1@1000";
            String aClassStr = "1000@0";
            v.add(aInstStr, aClassStr);  // A -->(class) --> A.class.

            A a2Inst = new A();
            setTag(a2Inst, 2);
            aInst.foo = a2Inst;
            String a2InstStr = "2@1000";
            v.add(a2InstStr, aClassStr);  // A2 -->(class) --> A.class.
            v.add(aInstStr, a2InstStr);   // A -->(field) --> A2.

            B bInst = new B();
            setTag(bInst, 3);
            aInst.foo2 = bInst;
            String bInstStr = "3@1001";
            String bClassStr = "1001@0";
            v.add(bInstStr, bClassStr);  // B -->(class) --> B.class.
            v.add(aInstStr, bInstStr);   // A -->(field) --> B.

            A a3Inst = new A();
            setTag(a3Inst, 4);
            bInst.bar = a3Inst;
            String a3InstStr = "4@1000";
            v.add(a3InstStr, aClassStr);  // A3 -->(class) --> A.class.
            v.add(bInstStr, a3InstStr);   // B -->(field) --> A3.

            C cInst = new C();
            setTag(cInst, 5);
            bInst.bar2 = cInst;
            String cInstStr = "5@1000";
            String cClassStr = "1002@0";
            v.add(cInstStr, cClassStr);  // C -->(class) --> C.class.
            v.add(bInstStr, cInstStr);   // B -->(field) --> C.

            A a4Inst = new A();
            setTag(a4Inst, 6);
            cInst.baz = a4Inst;
            String a4InstStr = "6@1000";
            v.add(a4InstStr, aClassStr);  // A4 -->(class) --> A.class.
            v.add(cInstStr, a4InstStr);   // C -->(field) --> A4.

            cInst.baz2 = aInst;
            v.add(cInstStr, aInstStr);  // C -->(field) --> A.

            A[] aArray = new A[2];
            setTag(aArray, 500);
            aArray[1] = a2Inst;
            cInst.array = aArray;
            String aArrayStr = "500@0";
            v.add(cInstStr, aArrayStr);
            v.add(aArrayStr, a2InstStr);

            return aInst;
        }
    }

    public static class A {
        public A foo;
        public A foo2;

        public A() {}
        public A(A a, A b) {
            foo = a;
            foo2 = b;
        }
    }

    public static class B extends A {
        public A bar;
        public A bar2;

        public B() {}
        public B(A a, A b) {
            bar = a;
            bar2 = b;
        }
    }

    public static interface I1 {
        public final static int i1Field = 1;
    }

    public static interface I2 extends I1 {
        public final static int i2Field = 2;
    }

    public static class C extends B implements I2 {
        public A baz;
        public A baz2;
        public A[] array;

        public C() {}
        public C(A a, A b) {
            baz = a;
            baz2 = b;
        }
    }

    private static interface Inf1 {
        public final static int A = 1;
    }

    private static interface Inf2 extends Inf1 {
        public final static int B = 1;
    }

    private static class IntObject implements Inf1 {
        byte b = (byte)1;
        char c= 'a';
        short s = (short)2;
        int i = 3;
        long l = 4;
        Object o = new Object();
        static int sI = 5;
    }

    private static class FloatObject extends IntObject implements Inf2 {
        float f = 1.23f;
        double d = 1.23;
        Object p = new Object();
        static int sI = 6;
    }

    public static class Verifier {
        // Should roots with vreg=-1 be printed?
        public final static boolean PRINT_ROOTS_WITH_UNKNOWN_VREG = false;

        public static class Node {
            public String referrer;

            public HashSet<String> referrees = new HashSet<>();

            public Node(String r) {
                referrer = r;
            }

            public boolean isRoot() {
                return referrer.startsWith("root@");
            }
        }

        HashMap<String, Node> nodes = new HashMap<>();

        public Verifier() {
        }

        public void add(String referrer, String referree) {
            if (!nodes.containsKey(referrer)) {
                nodes.put(referrer, new Node(referrer));
            }
            if (referree != null) {
                nodes.get(referrer).referrees.add(referree);
            }
        }

        public void process(String[] lines, String additionalEnabledReferrer, boolean filtered) {
            // This method isn't optimal. The loops could be merged. However, it's more readable if
            // the different parts are separated.

            ArrayList<String> rootLines = new ArrayList<>();
            ArrayList<String> nonRootLines = new ArrayList<>();

            // Check for consecutive chunks of referrers. Also ensure roots come first.
            {
                String currentHead = null;
                boolean rootsDone = false;
                HashSet<String> completedReferrers = new HashSet<>();
                for (String l : lines) {
                    String referrer = getReferrer(l);

                    if (isRoot(referrer)) {
                        if (rootsDone) {
                            System.out.println("ERROR: Late root " + l);
                            print(lines);
                            return;
                        }
                        rootLines.add(l);
                        continue;
                    }

                    rootsDone = true;

                    if (currentHead == null) {
                        currentHead = referrer;
                    } else {
                        // Ignore 0@0, as it can happen at any time (as it stands for all
                        // other objects).
                        if (!currentHead.equals(referrer) && !referrer.equals("0@0")) {
                            completedReferrers.add(currentHead);
                            currentHead = referrer;
                            if (completedReferrers.contains(referrer)) {
                                System.out.println("Non-contiguous referrer " + l);
                                print(lines);
                                return;
                            }
                        }
                    }
                    nonRootLines.add(l);
                }
            }

            // Sort (root order is not specified) and print the roots.
            // TODO: What about extra roots? JNI and the interpreter seem to introduce those
            //       (though it isn't clear why a debuggable-AoT test doesn't have the same,
            //       at least for locals). For now, swallow duplicates, and resolve once we
            //       have the metadata for the roots.
            {
                Collections.sort(rootLines);
                String lastRoot = null;
                for (String l : rootLines) {
                    if (lastRoot != null && lastRoot.equals(l)) {
                        continue;
                    }
                    lastRoot = l;
                    if (!PRINT_ROOTS_WITH_UNKNOWN_VREG && l.indexOf("vreg=-1") > 0) {
                        continue;
                    }
                    System.out.println(l);
                }
            }

            if (filtered) {
                // If we aren't tracking dependencies, just sort the lines and print.
                // TODO: As the verifier is currently using the output lines to track dependencies,
                //       we cannot verify that output is correct when parts of it are suppressed by
                //       filters. To correctly track this we need to take node information into
                //       account, and actually analyze the graph.
                Collections.sort(nonRootLines);
                for (String l : nonRootLines) {
                    System.out.println(l);
                }

                System.out.println("---");
                return;
            }

            // Iterate through the lines, keeping track of which referrers are visited, to ensure
            // the order is acceptable.
            HashSet<String> enabled = new HashSet<>();
            if (additionalEnabledReferrer != null) {
                enabled.add(additionalEnabledReferrer);
            }
            // Always add "0@0".
            enabled.add("0@0");

            for (String l : lines) {
                String referrer = getReferrer(l);
                String referree = getReferree(l);
                if (isRoot(referrer)) {
                    // For a root src, just enable the referree.
                    enabled.add(referree);
                } else {
                    // Check that the referrer is enabled (may be visited).
                    if (!enabled.contains(referrer)) {
                        System.out.println("Referrer " + referrer + " not enabled: " + l);
                        print(lines);
                        return;
                    }
                    enabled.add(referree);
                }
            }

            // Now just sort the non-root lines and output them
            Collections.sort(nonRootLines);
            for (String l : nonRootLines) {
                System.out.println(l);
            }

            System.out.println("---");
        }

        public static boolean isRoot(String ref) {
            return ref.startsWith("root@");
        }

        private static String getReferrer(String line) {
            int i = line.indexOf(" --");
            if (i <= 0) {
                throw new IllegalArgumentException(line);
            }
            int j = line.indexOf(' ');
            if (i != j) {
                throw new IllegalArgumentException(line);
            }
            return line.substring(0, i);
        }

        private static String getReferree(String line) {
            int i = line.indexOf("--> ");
            if (i <= 0) {
                throw new IllegalArgumentException(line);
            }
            int j = line.indexOf(' ', i + 4);
            if (j < 0) {
                throw new IllegalArgumentException(line);
            }
            return line.substring(i + 4, j);
        }

        private static void print(String[] lines) {
            for (String l : lines) {
                System.out.println(l);
            }
        }
    }

    private static void setTag(Object o, long tag) {
        Main.setTag(o, tag);
    }
    private static long getTag(Object o) {
        return Main.getTag(o);
    }

    private static native boolean checkInitialized(Class<?> klass);
    private static native void setupGcCallback();
    private static native void enableGcTracking(boolean enable);
    private static native int getGcStarts();
    private static native int getGcFinishes();
    private static native void forceGarbageCollection();

    private static native void checkForExtensionApis();
    private static native int getObjectHeapId(long tag);
    private static native String getHeapName(int heapId);
    private static native void checkGetObjectHeapIdInCallback(long tag, int heapId);

    public static native String[] followReferences(int heapFilter, Class<?> klassFilter,
            Object initialObject, int stopAfter, int followSet, Object jniRef);
    public static native String[] followReferencesString(Object initialObject);
    public static native String followReferencesPrimitiveArray(Object initialObject);
    public static native String followReferencesPrimitiveFields(Object initialObject);

    private static native void iterateThroughHeapExt();

    private static native void registerClass(long tag, Object obj);
}

Messung V0.5 in Prozent
C=89 H=97 G=93

¤ Dauer der Verarbeitung: 0.14 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.