-
Bug
-
Resolution: Unresolved
-
P4
-
None
-
1.3.0, 1.3.1, 1.4.0
-
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",
Synthetic.class.getDeclaredConstructors());
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!
System.out.println(Synthetic.class
.getDeclaredMethod("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]);
System.out.println("]");
}
}
=========
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)
======================================================================
- duplicates
-
JDK-4546736 (reflect) class literals adds unexpected synthetic Fields to class
-
- Closed
-
-
JDK-4526329 (reflect) Reflection should expose which members are synthetic
-
- Closed
-
- relates to
-
JDK-4891872 (reflect) Extend reflection to support generics, metadata and JSR201 features
-
- Resolved
-
-
JDK-4094180 # Synthetic names can conflict with explicit declaration
-
- Closed
-