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

Quelle  Main.java

  Sprache: JAVA
 

/*
 * Copyright (C) 2017 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 art.*;
import java.lang.ref.*;
import java.lang.reflect.*;
import java.util.*;
import java.util.function.Consumer;
import sun.misc.Unsafe;

public class Main {
  public static class Transform {
    static {
    }

    public static Object SECRET_ARRAY = new byte[] {1234};
    public static long SECRET_NUMBER = 42;

    public static void foo() {}
  }

  /* Base64 for
   * public static class Trasform {
   *   static {}
   *   public static Object AAA_PADDING;
   *   public static Object SECRET_ARRAY;
   *   public static long SECRET_NUMBER;
   *   public static void foo() {}
   *   public static void bar() {}
   * }
   */

  public static final byte[] REDEFINED_DEX_FILE =
      Base64.getDecoder()
          .decode(
              "ZGV4CjAzNQDdmsOAlizFD4Ogb6+/mfSdVzhmL8e/mRcYBAAAcAAAAHhWNBIAAAAAAAAAAGADAAAU"
                  + "AAAAcAAAAAcAAADAAAAAAQAAANwAAAADAAAA6AAAAAUAAAAAAQAAAQAAACgBAADQAgAASAEAAKwB"
                  + "AAC2AQAAvgEAAMsBAADOAQAA4AEAAOgBAAAMAgAALAIAAEACAABLAgAAWQIAAGgCAABzAgAAdgIA"
                  + "AIMCAACIAgAAjQIAAJMCAACaAgAAAwAAAAQAAAAFAAAABgAAAAcAAAAIAAAADQAAAA0AAAAGAAAA"
                  + "AAAAAAEABQACAAAAAQAFAAoAAAABAAAACwAAAAEAAAAAAAAAAQAAAAEAAAABAAAADwAAAAEAAAAQ"
                  + "AAAABQAAAAEAAAABAAAAAQAAAAUAAAAAAAAACQAAAFADAAAhAwAAAAAAAAAAAAAAAAAAmgEAAAEA"
                  + "AAAOAAAAAQABAAEAAACeAQAABAAAAHAQBAAAAA4AAAAAAAAAAACiAQAAAQAAAA4AAAAAAAAAAAAA"
                  + "AKYBAAABAAAADgAHAA4ABgAOAAsADgAKAA4AAAAIPGNsaW5pdD4ABjxpbml0PgALQUFBX1BBRERJ"
                  + "TkcAAUoAEExNYWluJFRyYW5zZm9ybTsABkxNYWluOwAiTGRhbHZpay9hbm5vdGF0aW9uL0VuY2xv"
                  + "c2luZ0NsYXNzOwAeTGRhbHZpay9hbm5vdGF0aW9uL0lubmVyQ2xhc3M7ABJMamF2YS9sYW5nL09i"
                  + "amVjdDsACU1haW4uamF2YQAMU0VDUkVUX0FSUkFZAA1TRUNSRVRfTlVNQkVSAAlUcmFuc2Zvcm0A"
                  + "AVYAC2FjY2Vzc0ZsYWdzAANiYXIAA2ZvbwAEbmFtZQAFdmFsdWUAdn5+RDh7ImNvbXBpbGF0aW9u"
                  + "LW1vZGUiOiJkZWJ1ZyIsIm1pbi1hcGkiOjEsInNoYS0xIjoiYTgzNTJmMjU0ODg1MzYyY2NkOGQ5"
                  + "MDlkMzUyOWM2MDA5NGRkODk2ZSIsInZlcnNpb24iOiIxLjYuMjAtZGV2In0AAgMBEhgCAgQCDgQJ"
                  + "ERcMAwAEAAAJAQkBCQCIgATIAgGBgATcAgEJ9AIBCYgDAAAAAAACAAAAEgMAABgDAABEAwAAAAAA"
                  + "AAAAAAAAAAAADwAAAAAAAAABAAAAAAAAAAEAAAAUAAAAcAAAAAIAAAAHAAAAwAAAAAMAAAABAAAA"
                  + "3AAAAAQAAAADAAAA6AAAAAUAAAAFAAAAAAEAAAYAAAABAAAAKAEAAAEgAAAEAAAASAEAAAMgAAAE"
                  + "AAAAmgEAAAIgAAAUAAAArAEAAAQgAAACAAAAEgMAAAAgAAABAAAAIQMAAAMQAAACAAAAQAMAAAYg"
                  + "AAABAAAAUAMAAAAQAAABAAAAYAMAAA==");

  private interface TConsumer<T> {
    public void accept(T t) throws Exception;
  }

  private interface ResetIterator<T> extends Iterator<T> {
    public void reset();
  }

  private static final class BaseResetIter implements ResetIterator<Object[]> {
    private boolean have_next = true;

    public Object[] next() {
      if (have_next) {
        have_next = false;
        return new Object[0];
      } else {
        throw new NoSuchElementException("only one element");
      }
    }

    public boolean hasNext() {
      return have_next;
    }

    public void reset() {
      have_next = true;
    }
  }

  public static void main(String[] args) throws Exception {
    System.loadLibrary(args[0]);
    Redefinition.setTestConfiguration(Redefinition.Config.COMMON_REDEFINE);

    // Get the Unsafe object.
    Field f = Unsafe.class.getDeclaredField("THE_ONE");
    f.setAccessible(true);
    Unsafe u = (Unsafe) f.get(null);

    // Get the offsets into the original Transform class of the fields
    long off_secret_array = genericFieldOffset(Transform.class.getDeclaredField("SECRET_ARRAY"));
    long off_secret_number = genericFieldOffset(Transform.class.getDeclaredField("SECRET_NUMBER"));

    System.out.println("Reading normally.");
    System.out.println("\tOriginal secret number is: " + Transform.SECRET_NUMBER);
    System.out.println("\tOriginal secret array is: " + Arrays.toString((byte[])Transform.SECRET_ARRAY));
    System.out.println("Using unsafe to access values directly from memory.");
    System.out.println(
        "\tOriginal secret number is: " + u.getLong(Transform.class, off_secret_number));
    System.out.println(
        "\tOriginal secret array is: "
            + Arrays.toString((byte[]) u.getObject(Transform.class, off_secret_array)));

    // Redefine in a way that changes the offsets.
    Redefinition.doCommonStructuralClassRedefinition(Transform.class, REDEFINED_DEX_FILE);

    // Make sure the value is the same.
    System.out.println("Reading normally post redefinition.");
    System.out.println("\tPost-redefinition secret number is: " + Transform.SECRET_NUMBER);
    System.out.println("\tPost-redefinition secret array is: " + Arrays.toString((byte[])Transform.SECRET_ARRAY));

    // Get the (old) obsolete class from the ClassExt
    Field ext_field = Class.class.getDeclaredField("extData");
    ext_field.setAccessible(true);
    Object ext_data = ext_field.get(Transform.class);
    Field oc_field = ext_data.getClass().getDeclaredField("obsoleteClass");
    oc_field.setAccessible(true);
    Class<?> obsolete_class = (Class<?>) oc_field.get(ext_data);

    // Try reading the fields directly out of memory using unsafe.
    System.out.println("Obsolete class is: " + obsolete_class);
    System.out.println("Using unsafe to access obsolete values directly from memory.");
    System.out.println(
        "\tObsolete secret number is: " + u.getLong(obsolete_class, off_secret_number));
    System.out.println(
        "\tObsolete secret array is: "
            + Arrays.toString((byte[]) u.getObject(obsolete_class, off_secret_array)));

    // Try calling all the public, non-static methods on the obsolete class. Make sure we cannot get
    // j.l.r.{Method,Field} objects or instances.
    TConsumer<Class> cc =
        (Class c) -> {
          for (Method m : Class.class.getDeclaredMethods()) {
            if (Modifier.isPublic(m.getModifiers()) && !Modifier.isStatic(m.getModifiers())) {
              Iterable<Object[]> iter = CollectParameterValues(m, obsolete_class);
              System.out.println("Calling " + m + " with params: " + iter);
              for (Object[] arr : iter) {
                try {
                  System.out.println(
                      m
                          + " on "
                          + safePrint(c)
                          + " with "
                          + deepPrint(arr)
                          + " = "
                          + safePrint(m.invoke(c, arr)));
                } catch (Throwable e) {
                  System.out.println(
                      m + " with " + deepPrint(arr) + " throws " + safePrint(e) + ": " + safePrint(e.getCause()));
                }
              }
            }
          }
        };
    System.out.println("\n\nUsing obsolete class object!\n\n");
    cc.accept(obsolete_class);
    System.out.println("\n\nUsing non-obsolete class object!\n\n");
    cc.accept(Transform.class);
  }

  public static Iterable<Object[]> CollectParameterValues(Method m, Class<?> obsolete_class) throws Exception {
    Class<?>[] types = m.getParameterTypes();
    final Object[][] params = new Object[types.length][];
    for (int i = 0; i < types.length; i++) {
      if (types[i].equals(Class.class)) {
        params[i] =
            new Object[] {
              null, Object.class, obsolete_class, Transform.classLong.TYPE, Class.class
            };
      } else if (types[i].equals(Boolean.TYPE)) {
        params[i] = new Object[] {Boolean.TRUEBoolean.FALSE};
      } else if (types[i].equals(String.class)) {
        params[i] = new Object[] {"NOT_USED_STRING""foo""SECRET_ARRAY"};
      } else if (types[i].equals(Object.class)) {
        params[i] = new Object[] {null"foo""NOT_USED_STRING", Transform.class};
      } else if (types[i].isArray()) {
        params[i] = new Object[] {new Object[0], new Class[0], null};
      } else {
        throw new Exception("Unknown type " + types[i] + " at " + i + " in " + m);
      }
    }
    // Build the reset-iter.
    ResetIterator<Object[]> iter = new BaseResetIter();
    for (int i = params.length - 1; i >= 0; i--) {
      iter = new ComboIter(Arrays.asList(params[i]), iter);
    }
    final Iterator<Object[]> fiter = iter;
    // Wrap in an iterator with a useful toString method.
    return new Iterable<Object[]>() {
      public Iterator<Object[]> iterator() { return fiter; }
      public String toString() { return deepPrint(params); }
    };
  }

  public static String deepPrint(Object[] o) {
    return Arrays.toString(
        Arrays.stream(o)
            .map(
                (x) -> {
                  if (x == null) {
                    return "null";
                  } else if (x.getClass().isArray()) {
                    if (((Object[]) x).length == 0) {
                      return "new " + x.getClass().getComponentType().getName() + "[0]";
                    } else {
                      return deepPrint((Object[]) x);
                    }
                  } else {
                    return safePrint(x);
                  }
                })
            .toArray());
  }

  public static String safePrint(Object o) {
    if (o instanceof ClassLoader) {
      return o.getClass().getName();
    } else if (o == null) {
      return "null";
    } else if (o instanceof Exception) {
      String res = o.toString();
      if (res.endsWith("-transformed)")) {
        res = res.substring(0, res.lastIndexOf(" ")) + " <transformed-jar>)";
      } else if (res.endsWith(".jar)")) {
        res = res.substring(0, res.lastIndexOf(" ")) + " <original-jar>)";
      }
      return res;
    } else if (o instanceof Transform) {
      return "Transform Instance";
    } else if (o instanceof Class && isObsoleteObject((Class) o)) {
      return "(obsolete)" + o.toString();
    } else if (o.getClass().isArray()) {
      return Arrays.toString((Object[])o);
    } else {
      return o.toString();
    }
  }

  private static class ComboIter implements ResetIterator<Object[]> {
    private ResetIterator<Object[]> next;
    private Object cur;
    private boolean first;
    private Iterator<Object> my_vals;
    private Iterable<Object> my_vals_reset;

    public Object[] next() {
      if (!next.hasNext()) {
        cur = my_vals.next();
        first = false;
        if (next != null) {
          next.reset();
        }
      }
      if (first) {
        first = false;
        cur = my_vals.next();
      }
      Object[] nv = next.next();
      Object[] res = new Object[nv.length + 1];
      res[0] = cur;
      for (int i = 0; i < nv.length; i++) {
        res[i + 1] = nv[i];
      }
      return res;
    }

    public boolean hasNext() {
      return next.hasNext() || my_vals.hasNext();
    }

    public void reset() {
      my_vals = my_vals_reset.iterator();
      next.reset();
      cur = null;
      first = true;
    }

    public ComboIter(Iterable<Object> this_reset, ResetIterator<Object[]> next_reset) {
      my_vals_reset = this_reset;
      next = next_reset;
      reset();
    }
  }

  public static native long genericFieldOffset(Field f);

  public static native boolean isObsoleteObject(Class c);
}

Messung V0.5 in Prozent
C=81 H=89 G=84

¤ 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.