Closed sourceforge-issue-exporter closed 1 year ago
Logged In: NO
if the method is retrieved like:
MyParent.class.getMethod("...")
all will work fine, while the following will not work without setAccessible(true):
myParentInstance.getClass().getMethod("...")
please observer the following sample, with a slight'ly modified MyParent:
----- file: foo/ReflectTest
package foo;
public class ReflectTest { public static void main(String[] args) { MyParent myParent = MyParent.getInstance();
// the following fails to work correctly
//Method method =
myParent.getClass().getMethod("getValue", new Class[]
{Number.class});
// this one works ok Method method = MyParent.class.getMethod("getValue", new Class[] {Number.class});
System.out.println(method.invoke(myParent, new Object[] {new Long(123)})); } }
----- file: bar/MyParent
package bar;
public abstract class MyParent { public static MyParent getInstance() { return new MyClass(); }
public abstract int getValue(Number number);
private static class MyClass extends MyParent { public int getValue(Number number) { return 1; } } }
-----
Guven Demir guven dot demir at telenity dot com dot tr
Original comment by: nobody
Cannot even evaluate the class definition:
bsh % public abstract class MyParent {
public static final MyParent INSTANCE = new MyClass();
public abstract int getValue(Number number);
private static class MyClass extends MyParent {
public int getValue(Number number) {
return 1;
}
}
}
// Error: Evaluation Error: Class: MyParent not found in namespace : at Line: 5 : in file: <unknown file> : MyParent
Line 5 is at the inner class definition. source file: MyParent.java.txt
This compiles with javac so we should at least be able to evaluate the class.
This is not a problem:
BeanShell 3.0.0-SNAPSHOT.2151
bsh % public abstract class MyParent {}
--> $0 = class MyParent :Class
And neither is:
BeanShell 3.0.0-SNAPSHOT.2151
bsh % public abstract class MyParent {
public static final MyParent INSTANCE = new MyClass();
}
--> $0 = class MyParent :Class
And once parent exists the inner class succeeds:
BeanShell 3.0.0-SNAPSHOT.2151
public abstract class MyParent {}
--> $0 = class MyParent :Class
public abstract class MyParent {
private static class MyClass extends MyParent {
public int getValue(Number number) {
return 1;
}
}
}
--> $1 = class MyParent :Class
BeanShell 3.0.0-SNAPSHOT.2151
debug();
// Debug: On
--> void
public abstract class MyParent {
private static class MyClass extends MyParent {
public int getValue(Number number) {
return 1;
}
}
}
>ClassDeclaration: MyParent
> Block: static=false, synchronized=false
> ClassDeclaration: MyClass
> AmbiguousName: MyParent
> Block: static=false, synchronized=false
> MethodDeclaration: getValue
> ReturnType: void=false
> Type
> PrimitiveType: int
> FormalParameters
> FormalParameter: number, final=false, varargs=false
> Type
> AmbiguousName: Number
> Block: static=false, synchronized=false
> ReturnStatement: "return"
> Assignment
> PrimaryExpression
> Literal: 1
// Debug: Trying to load class: MyParent
// Debug: absoluteNonClass list hit: MyParent
// Debug: getClass(): MyParent not found in NameSpace: MyParent (bsh.NameSpace@4d591d15) (class)
// Debug: Trying to load class: java.lang.MyParent
// Debug: Trying to load class: java.io.MyParent
// Debug: Trying to load class: java.util.MyParent
// Debug: Trying to load class: java.util.regex.MyParent
// Debug: Trying to load class: java.util.stream.MyParent
// Debug: Trying to load class: java.util.function.MyParent
// Debug: Trying to load class: java.net.MyParent
// Debug: absoluteNonClass list hit: MyParent
// Debug: absoluteNonClass list hit: MyParent
// Debug: getClass(): MyParent not found in NameSpace: global (bsh.NameSpace@65ae6ba4)
// Debug: trying class: MyParent
// Debug: absoluteNonClass list hit: MyParent
// Debug: absoluteNonClass list hit: MyParent
// Debug: getClass(): MyParent not found in NameSpace: MyParent (bsh.NameSpace@4d591d15) (class)
// Debug: absoluteNonClass list hit: java.lang.MyParent
// Debug: absoluteNonClass list hit: java.io.MyParent
// Debug: absoluteNonClass list hit: java.util.MyParent
// Debug: absoluteNonClass list hit: java.util.regex.MyParent
// Debug: absoluteNonClass list hit: java.util.stream.MyParent
// Debug: absoluteNonClass list hit: java.util.function.MyParent
// Debug: absoluteNonClass list hit: java.net.MyParent
// Debug: absoluteNonClass list hit: MyParent
// Debug: absoluteNonClass list hit: MyParent
// Debug: getClass(): MyParent not found in NameSpace: global (bsh.NameSpace@65ae6ba4)
// Debug: not a class, trying var prefix MyParent
// Debug: Get method: getMyParent NameSpace: MyParent (bsh.NameSpace@4d591d15) (class)
// Debug: Get method: getMyParent NameSpace: global (bsh.NameSpace@65ae6ba4)
// Debug: Get method: isMyParent NameSpace: MyParent (bsh.NameSpace@4d591d15) (class)
// Debug: Get method: isMyParent NameSpace: global (bsh.NameSpace@65ae6ba4)
// Error: Evaluation Error: Class: MyParent not found in namespace : at Line: 5 : in file: <unknown file> : MyParent
bsh.EvalError: Class: MyParent not found in namespace : at Line: 5 : in file: <unknown file> : MyParent
at bsh.BSHAmbiguousName.toClass(BSHAmbiguousName.java:66)
at bsh.BSHClassDeclaration.generateClass(BSHClassDeclaration.java:78)
at bsh.BSHClassDeclaration.eval(BSHClassDeclaration.java:63)
at bsh.BSHBlock.evalBlock(BSHBlock.java:132)
at bsh.ClassGenerator.generateClassImpl(ClassGenerator.java:89)
at bsh.ClassGenerator.generateClass(ClassGenerator.java:55)
at bsh.BSHClassDeclaration.generateClass(BSHClassDeclaration.java:104)
at bsh.BSHClassDeclaration.eval(BSHClassDeclaration.java:63)
at bsh.Interpreter.run(Interpreter.java:509)
at bsh.Interpreter.main(Interpreter.java:452)
Caused by: java.lang.ClassNotFoundException: Class: MyParent not found in namespace
at bsh.Name.toClass(Name.java:642)
at bsh.BSHAmbiguousName.toClass(BSHAmbiguousName.java:64)
... 9 more
Here we start with Generate class where before the first instinct was to try and load it. Chicken or egg problem.
BeanShell 3.0.0-SNAPSHOT.2151
debug();
// Debug: On
--> void
public abstract class MyParent {}
>ClassDeclaration: MyParent
> Block: static=false, synchronized=false
// Debug: Generate class CLASS MyParent cons:0 meths:0 vars:0
// Debug: Trying to load class: MyParent
// Debug: Define MyParent as class MyParent
// Debug: NameSpace: MyParent (bsh.NameSpace@6833ce2c) (class) (class static)
--> $0 = class MyParent :Class
While generating the class the block is evaluated, specifically:
// Evaluate any inner class class definitions in the block
// effectively recursively call this method for contained classes first
So this means we cannot have eggs from the same chicken.
I went on a tangent and missed the original instruction:
1) Compile this code
public abstract class MyParent {
public static final MyParent INSTANCE = new MyClass();
public abstract int getValue(Number number);
private static class MyClass extends MyParent {
public int getValue(Number number) {
return 1;
}
}
}
2) Start the beanshell console. 3) Add the output from the above compilation to the classpath. 4) Type
MyParent.INSTANCE.getValue(new Integer(1));
Result:
BeanShell 3.0.0-SNAPSHOT.3578
bsh % MyParent.class;
--> $0 = class MyParent :Class
bsh % MyParent.INSTANCE;
--> $1 = MyParent$MyClass@41a4555e :MyParent$MyClass
bsh % MyParent.INSTANCE.getValue(1);
--> $2 = 1I :int
bsh % MyParent.INSTANCE.getValue(new Integer(1));
--> $3 = 1I :int
Works as expected...
The issue that BeanShell cannot interpret the valid java source from this example has been moved to #694
Closed as the issue reported by OP is resolved.
When calling a public method on a package scope inner class, which extends a public superclass you get an IllegalAccessException. This is caused by one of the top rated Sun Java bugs ( http://bugs.sun.com/bugdatabase/view\_bug.do? bug_id=4071957 ), but can be fixed in Beanshell with a one line fix.
It appears in the current CVS version of Beanshell (2.0b2). You might want to add your bug votes to this bug on Sun's bug DB if you have any spare.
To reproduce: -------------
1) Compile this code
2) Start the beanshell console.
3) Add the output from the above compilation to the classpath.
4) Type foo.MyParent.INSTANCE.getValue(new Integer (1));
To fix (one line): --------------- Modify
if ( method != null && !Modifier.isPublic( method.getModifiers() ) ) { try { ReflectManager.RMSetAccessible( method ); } catch ( UtilEvalError e ) { /*ignore*/ } }
To (you are just adding a test for a non-public class)
if ( method != null && (!Modifier.isPublic( method.getModifiers() ) ||
Modifier.isPublic(method.getDeclaringClass().getModifiers ())) ) { try { ReflectManager.RMSetAccessible( method ); } catch ( UtilEvalError e ) { /*ignore*/ } }
Reported by: nfortescue
Original Ticket: "beanshell/bugs/197":https://sourceforge.net/p/beanshell/bugs/197