Original problem in following mail. I implemented JDK1.1 compatibility and performance

improvements:

Subject:
        Rhino: Problem in NativeJavaMethod
   Date:
        Tue, 14 Aug 2001 10:23:35 +0200
   From:
        felix.meschberger@day.com
     To:
        Norris Boyd <nboyd@atg.com>




Hi Norris,

While working with wrapped Java classes we discovered a problem in
NativeJavaMethod : If the public method to be called is part of a
non-public class, the Sun Java VM throws an IllegalAccessException. This
bug in the Sun VM has been reported as Bug 4071593 to Sun, but has not been
resolved since....

I implemented a circumvention, for which I provide you the patch. I quickly
tested it, and it seems to work.

Regards
Felix

And here's the patch :

diff -w -r1.19 NativeJavaMethod.java
227a228,234
>        /**
>         * Due to a bug in Suns VM, public methods in private
>         * classes are not accessible by default (Sun Bug #4071593).
>         * We have to explicitly set the method accessible beforehand
>         */
>        meth.setAccessible(true);
>

-----------------------------------------------------------------
This message is a private communication. If you are not the intended
recipient, please do not read, copy, or use it, and do not disclose it
to others. Please notify the sender of the delivery error by replying to
this message, and then delete it from your system. Thank you.
The sender does not assume any liability for timely, trouble-free,
complete, virus free, secure, error free or uninterrupted arrival of
this e-mail. For verification please request a hard copy version.

mailto:felix.meschberger@day.com
http://www.day.com

Felix Meschberger
Development
Day Interactive AG
Steinenberg 21-23
4001 Basel
Switzerland

T  41 61 226 98 98
F  41 61 226 98 97
This commit is contained in:
nboyd%atg.com 2001-08-24 20:01:49 +00:00
parent c8695a1a29
commit 115380ea02

View File

@ -220,44 +220,68 @@ public class NativeJavaMethod extends NativeFunction implements Function {
}
javaObject = ((Wrapper) o).unwrap();
}
try {
if (debug) {
printDebug("Calling ", meth, args);
}
retry:
for (int attempt=0; ; attempt++) {
try {
if (debug) {
printDebug("Calling ", meth, args);
}
/**
* Due to a bug in Suns VM, public methods in private
* classes are not accessible by default (Sun Bug #4071593).
* We have to explicitly set the method accessible beforehand
*/
meth.setAccessible(true);
Object retval = meth.invoke(javaObject, args);
Class staticType = meth.getReturnType();
Object retval = meth.invoke(javaObject, args);
Class staticType = meth.getReturnType();
if (debug) {
Class actualType = (retval == null) ? null : retval.getClass();
System.err.println(" ----- Returned " + retval +
" actual = " + actualType +
" expect = " + staticType);
}
if (debug) {
Class actualType = (retval == null) ? null
: retval.getClass();
System.err.println(" ----- Returned " + retval +
" actual = " + actualType +
" expect = " + staticType);
}
Object wrapped = NativeJavaObject.wrap(scope, retval, staticType);
Object wrapped = NativeJavaObject.wrap(scope, retval, staticType);
if (debug) {
Class actualType = (wrapped == null) ? null : wrapped.getClass();
System.err.println(" ----- Wrapped as " + wrapped +
" class = " + actualType);
}
if (debug) {
Class actualType = (wrapped == null) ? null
: wrapped.getClass();
System.err.println(" ----- Wrapped as " + wrapped +
" class = " + actualType);
}
if (wrapped == Undefined.instance)
if (wrapped == Undefined.instance)
return wrapped;
if (wrapped == null && staticType == Void.TYPE)
return Undefined.instance;
return wrapped;
if (wrapped == null && staticType == Void.TYPE)
return Undefined.instance;
return wrapped;
} catch (IllegalAccessException accessEx) {
throw Context.reportRuntimeError(accessEx.getMessage());
} catch (InvocationTargetException e) {
throw JavaScriptException.wrapException(scope, e);
} catch (IllegalAccessException accessEx) {
if (Modifier.isPublic(meth.getModifiers()) && attempt == 0) {
/**
* Due to a bug in Suns VM, public methods in private
* classes are not accessible by default (Sun Bug #4071593).
* We have to explicitly set the method accessible
* via meth.setAccessible(true) but we have to use
* reflection because the setAccessible() in Method is
* not available under jdk 1.1. We wait until a failure
* to retry to avoid the overhead of this call on cases
* that don't require it.
*/
if (method_setAccessible != null) {
Object[] args_wrapper = { Boolean.TRUE };
try {
method_setAccessible.invoke(meth, args_wrapper);
}
catch (IllegalAccessException ex) { }
catch (IllegalArgumentException ex) { }
catch (InvocationTargetException ex) { }
}
continue retry;
}
throw Context.reportRuntimeError(
"While attempting to call \"" + meth.getName() +
"\" in class \"" + meth.getDeclaringClass().getName() +
"\" receieved " + accessEx.toString());
} catch (InvocationTargetException e) {
throw JavaScriptException.wrapException(scope, e);
}
}
}
@ -507,6 +531,17 @@ public class NativeJavaMethod extends NativeFunction implements Function {
return methods;
}
// Utility to call Class.getMethod and get null instead of thrown exceptions
private static Method getMethod(Class cl, String name, Class[] signature) {
try {
return cl.getMethod(name, signature);
}
catch (NoSuchMethodException ex) { }
catch (SecurityException ex) { }
return null;
}
private static final boolean debug = false;
private static void printDebug(String msg, Member member, Object[] args) {
@ -519,5 +554,10 @@ public class NativeJavaMethod extends NativeFunction implements Function {
}
Method methods[];
private static final Method method_setAccessible
= getMethod(Method.class,
"setAccessible", new Class[] { Boolean.TYPE });
}