Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-4407429

(reflect spec) doc presence of synthetic members



    • Fix Understood
    • generic, x86
    • generic, solaris_7, windows_2000


      Name: boT120536 Date: 01/23/2001

      java version "1.3.0"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.0-C)
      Java HotSpot(TM) Client VM (build 1.3.0-C, mixed mode)

      The reflection API is unclear as to whether synthetic members (classes,
      constructors, methods, and fields) are to show up during reflection. In my
      opinion, they should not be visible to reflection, as synthetic members are only
      meant to be accessed by trusted code generated by the compiler, not haphazardly
      by reflection. This is particularly true since other compilers do not
      have to follow the same naming convention as JDK; so simply compiling identical
      source on different compilers can lead to different program results, although
      Java source code is supposed to behave identically regardless of the compiler.

      However, if you do decide that synthetic members should be accessible, you
      should probably have a separate API to get to them (such as
      Class.getSyntheticMethod()), and you should include
      Modifier.SYNTHETIC as a way to identify such members. You may also consider
      adding appropriate Securities to the reflection of synthetic members, because
      there could be a security breach if a user can access the private members of a
      class by figuring out the right synthetic methods to reflect.

      It appears that JDK creates all its synthetic members with at most default
      (package) access, so a true security breach would require the rogue class belong
      to the same package or override access checking. Thus, a security model that
      prevents the addition of rogue classes to a package during the life of the
      VM/ClassLoader and that prevents overriding accessibility checks would safely
      thwart all attempts to breach a package from outside; then it is just a matter
      of only having trusted code within the package.

      import java.lang.reflect.*;

      public class Synthetic {
        public static void main(String[] args) {
          try {
      // the XXX.class access generates synthetic blank finals, and class$()
            output("methods in Synthetic", Synthetic.class.getDeclaredMethods());
            output("fields in Synthetic", Synthetic.class.getDeclaredFields());
            output("constructors in Synthetic",
            output("classes in Synthetic", Synthetic.class.getDeclaredClasses());
            output("methods in Sub", Sub.class.getDeclaredMethods());
            output("fields in Sub", Sub.class.getDeclaredFields());
            output("constructors in Sub", Sub.class.getDeclaredConstructors());
            output("classes in Sub", Sub.class.getDeclaredClasses());
      // invoke the synthetic class$() method on a completely unrelated class!
      new Class[] {String.class})
      .invoke(null, new Object[] {"java.lang.Integer"} ));
      // constructing a Sub generates a synthetic class in JDK1.3
            System.out.println("Sub contains " + new Synthetic().new Sub());
          } catch (Exception e) {

      // a default constructor is generated, but this is not synthetic
      // Synthetic() {}

      // i must be a private, non-constant to generate synthetic accessor method
        private int i = 1 + 2;

        class Sub {
      // private constructor requires synthetic constructor to access
          private Sub() {}
          public String toString() { return ""+i; }

        static void output(String prefix, Object[] array) {
          System.out.print(prefix + ":\n[" + (array.length > 0 ? array[0] : ""));
          for (int i=1; i<array.length; i++)
            System.out.print(",\n " + array[i]);

      output of Synthetic:
      methods in Synthetic
      [public static void Synthetic.main(java.lang.String[]),
       static int Synthetic.access$100(Synthetic), //synthetic
       static java.lang.Class Synthetic.class$(java.lang.String), //synthetic
       static void Synthetic.output(java.lang.Object[])]
      fields in Synthetic
      [private int Synthetic.i,
       static java.lang.Class Synthetic.class$Synthetic, //synthetic
       static java.lang.Class Synthetic.class$Synthetic$Sub, //synthetic
       static java.lang.Class Synthetic.class$java$lang$String] //synthetic
      constructors in Synthetic
      [public Synthetic()] // although this is generated, it is not synthetic
      classes in Synthetic
      [class Synthetic$1, //synthetic
       class Synthetic$Sub]
      methods in Sub
      [public java.lang.String Synthetic$Sub.toString()]
      fields in Sub
      [private final Synthetic Synthetic$Sub.this$0] //synthetic
      constructors in Sub
      [Synthetic$Sub(Synthetic,Synthetic$1), //synthetic
       private Synthetic$Sub(Synthetic)]
      classes in Sub
      class java.lang.Integer // We just abused the class$() method
      Sub contains 3

      import java.lang.reflect.*;

      public class Breach {
        public static void main(String[] args) {
          try {
            Method m = Synthetic.class
      .getDeclaredMethod("access$100", new Class[] {Synthetic.class} );
            Synthetic s = new Synthetic();
            System.out.println("I just read the private field Synthetic.i: " +
      m.invoke(s, new Object[] {s} ));
          } catch (Exception e) {
            System.out.println("Caught: " + e);
      output of Breach:
      I just read the private field Synthetic.i: 3
      (Review ID: 108233)


        Issue Links



              Unassigned Unassigned
              bonealsunw Bret O'neal (Inactive)
              0 Vote for this issue
              1 Start watching this issue