This is the mail archive of the
kawa@sources.redhat.com
mailing list for the Kawa project.
bug in invoke + reflection patch/improvement
- To: per at bothner dot com
- Subject: bug in invoke + reflection patch/improvement
- From: Martin Atzmueller <martin dot atzmueller at gmx dot net>
- Date: Wed, 23 Aug 2000 10:34:40 +0200 (MEST)
- Cc: kawa at sourceware dot cygnus dot com
Hi,
I've used Kawa a lot in implementing callbacks between Java->Scheme, and
vice versa.
There is a bug (feature :) in kawa, preventing 'invoke to work correctly
in
some cases.
Consider the following case:
When working interactively, Kawa does use reflection to access methods.
Say we have a non-accessible Super-Class P, implementing a public method
m,
and a SubClass C.
When trying to use Method m of P, JDK1.1 will not allow
it _using_ reflection. So Kawa, in the current version, will neither allow
it.
This does work in compiled Java Code, though.
Example:
class TClass1 {
public int print() {
System.out.println( "foo" );
return 1; } }
public class TClass2 extends TClass1 {
private int bla = -1;
public static void main( String[] args ) {
TClass2 tc = new TClass2();
tc.print(); } }
This code will fail:
(begin
(set! i (make 'TClass2))
(invoke i 'print))
additionally, we cannot access slot 'bla' of instance i.
Java 2 allows access to non-public fields, using Reflection.
I've implemented a 'ReflectionHelper' class, that allows interactive
(using
the listener) access to non-public objects.
This is appended at the bottom, together with all the patches to the
kawa-reflection-classes that were needed to make this work.
What do you think about this?
Will this be included in the next release?
I think it's a really neat feature, especially when debugging code.
Cheers,
Martin Atzmueller
Patches:
================
--- /home/atzmuel/local/src/kawa-1.6.70/gnu/expr/PrimProcedure.java Wed
Jun 7 20:23:31 2000
+++
/home/atzmuel/local/src/kawa-1.6.70-mna/gnu/expr/PrimProcedure.java Wed Aug 16 09:31:18 2000
@@ -133,6 +133,8 @@
{
Object[] pargs = new Object[arg_count];
System.arraycopy(rargs, 1, pargs, 0, arg_count);
+ gnu.kawa.reflect.ReflectionHelper.enableAccess( meth );
result = meth.invoke(rargs[0], pargs);
}
return retType.coerceToObject(result);
diff -u -r -w
/home/atzmuel/local/src/kawa-1.6.70/gnu/kawa/reflect/SlotGet.java /home/atzmuel/local/src/kawa-1.6.70-mna/gnu/kawa/reflect/SlotGet.java
--- /home/atzmuel/local/src/kawa-1.6.70/gnu/kawa/reflect/SlotGet.java Sun
Jun 18 08:56:20 2000
+++
/home/atzmuel/local/src/kawa-1.6.70-mna/gnu/kawa/reflect/SlotGet.java Thu Aug 17 11:17:47 2000
@@ -44,14 +44,8 @@
}
boolean illegalAccess = false;
java.lang.reflect.Field field;
- try
- {
- field = clas.getField(fname);
- }
- catch (Exception ex)
- {
- field = null;
- }
+
+ field = ReflectionHelper.getField( clas, fname );
if (field != null)
{
if (isStatic
diff -u -r -w
/home/atzmuel/local/src/kawa-1.6.70/gnu/kawa/reflect/SlotSet.java /home/atzmuel/local/src/kawa-1.6.70-mna/gnu/kawa/reflect/SlotSet.java
--- /home/atzmuel/local/src/kawa-1.6.70/gnu/kawa/reflect/SlotSet.java Mon
Jan 31 22:49:20 2000
+++
/home/atzmuel/local/src/kawa-1.6.70-mna/gnu/kawa/reflect/SlotSet.java Thu Aug 17 11:19:42 2000
@@ -16,12 +16,9 @@
Class clas = isStatic ? SlotGet.coerceToClass(obj) : obj.getClass();
try
{
- java.lang.reflect.Field field = clas.getField(name);
+ java.lang.reflect.Field field = ReflectionHelper.getField( clas,
name );
field.set(obj, interpreter.coerceFromObject(field.getType(),
value));
return;
- }
- catch (java.lang.NoSuchFieldException ex)
- {
}
catch (IllegalAccessException ex)
{
================
ReflectionHelper:
================
package gnu.kawa.reflect;
import java.lang.reflect.*;
import java.util.Vector;
import java.util.Hashtable;
/** This Class improves java-reflection access to both methods and fields.
* In versions of Java prior to Java 2, only public classes and members
* can be accessed reflectively. In Java 2, nonpublic classes and members
* can be accessed if the security manager allows it, and this feature is
* explicitly requested.
*
*
* Using this helper class, especially the 'enableAccess'-method,
non-public slots
* methods are made accessible.
* The private-access features are only available in the
"Runtime"-Kawa-Environment,
* e.g. when working interactively.
* It does not work in compiled code.
*/
public final class ReflectionHelper {
/** True if the JDK implements Java 2 or above. If this is
<code>true</true>, then non-public classes and members can be accessed.
*/
public static boolean isJava2;
static {
try {
Class.forName("java.lang.reflect.AccessibleObject");
} catch (ClassNotFoundException ex) {
isJava2 = false;
}
isJava2 = true;
}
/** Override Java-Access-control, if possible.*/
public static void enableAccess( Object obj ) {
setAccessible( obj, true );
}
// going thru reflection so this can be compiled using JDK1.1.
static Method setAccessibleMethod = null;
private static void setAccessible(Object obj, boolean accessible) {
try {
if (setAccessibleMethod == null) {
Class aclass =
Class.forName("java.lang.reflect.AccessibleObject");
setAccessibleMethod =
aclass.getMethod("setAccessible", new Class[]{
Boolean.TYPE });
}
setAccessibleMethod.invoke(obj, new Object[]{ Boolean.TRUE });
}
catch (Throwable e) {
System.out.println("Error trying to set accessibility for " +
obj);
}
}
public static java.lang.reflect.Field getField( Class clas, String
fname ) {
java.lang.reflect.Field field;
try {
field = clas.getField(fname);
}
catch ( NoSuchFieldException ex ) {
if ( isJava2 ) {
// try harder, using all declared fields.
java.lang.reflect.Field[] localFields = clas.getDeclaredFields();
for (int i = 0; i != localFields.length; i++) {
if (fname.equals(localFields[i].getName())) {
field = localFields[i];
ReflectionHelper.enableAccess( field );
return field;
}
}
// if not found, go up to superclass.
Class superClass = clas.getSuperclass();
if (superClass == null)
field = null;
else
return getField(superClass, fname);
}
else
field = null;
}
catch (Exception ex)
{
field = null;
}
return field;
}
}
--
Sent through GMX FreeMail - http://www.gmx.net