Closed Bug 8842 Opened 26 years ago Closed 14 years ago

Rhino : Public methods are lost when subclassed with a "non-public" class.

Categories

(Core Graveyard :: Java: Live Connect, defect, P3)

x86
Windows 98

Tracking

(Not tracked)

RESOLVED INCOMPLETE

People

(Reporter: time, Unassigned)

Details

Attachments

(1 file)

If I have a "public class SuperC", which has a method "public void pubmeth()", and then I subclass "SuperC", with "final class SubC", and I DO NOT define "pubmeth()" in "SubC", then when I have a "SubC" in my JavaScript, I can not see the method "pubmeth()". This is not correct. If I do a "SubC.instance.getClass().getMethods()", "pubmeth" is listed, and if I call "isPublic()" on pubmeth's Method, it returns true. Sounds like LiveConnect is mistakenly making the method private because the subclass is not explicitly declared as public (or because it is final?).
First, I couldn't duplicate your problem. (See my test case, below.) Second, LiveConnect uses getMethods() internally to enumerate the methods of a class, so it seems unlikely that the method would be enumerated when getMethods() is called "by hand", but not when called by LiveConnect. Possibly, this is a problem with your JVM. Which JVM are you using ? I used this test case with JDK1.1.7: public class SuperC { public SuperC() {super();} public int pubmeth() {return 7;} static public SubC instantiate() {return new SubC();} } final class SubC extends SuperC { } js> s = Packages.SuperC.instantiate() netscape.javascript.SubC@20684b js> for (p in s) print (p) pubmeth wait notifyAll notify toString equals hashCode getClass js> s.pubmeth() 7
posting message sent by tim in mail. ------ On Thu, Jun 24 1999, bugzilla-daemon@mozilla.org wrote: bugzil> + ------- Additional Comments From fur@netscape.com 06/24/99 10:18 ------- bugzil> + First, I couldn't duplicate your problem. (See my test case, below.) Bummer. bugzil> + Second, LiveConnect uses getMethods() internally to enumerate the methods of a bugzil> + class, so it seems unlikely that the method would be enumerated when bugzil> + getMethods() is called "by hand", but not when called by LiveConnect. Possibly, bugzil> + this is a problem with your JVM. Which JVM are you using ? I use Sun's JDK1.1.7B. The problem lies with a class 'com.sun.jndi.ldap.LdapAttribute', which subclasses 'javax.naming.directory.BasicAttribute'. I had been writing scripts that were calling 'getID()'. Suddenly, when I upgraded the ldap.jar, the code stopped working. I ran Mocha on the two versions of the class, and here are the diffs: ------------------------------------------------------------------------------- ----------- 12c12 < final synchronized class LdapAttribute extends BasicAttribute --- > public synchronized class LdapAttribute extends BasicAttribute 14,17c14,17 < private transient DirContext baseCtx; < private Name rdn; < private String baseCtxURL; < private Hashtable baseCtxEnv; --- > protected transient DirContext baseCtx; > protected Name rdn; > protected String baseCtxURL; > protected Hashtable baseCtxEnv; 26c26 < LdapAttribute(String string) --- > public LdapAttribute(String string) 32c32 < LdapAttribute(String string, Object object) --- > public LdapAttribute(String string, Object object) 38c38 < LdapAttribute(Attribute attribute, DirContext dirContext, Name name) --- > public LdapAttribute(Attribute attribute, DirContext dirContext, Name name) 49c49 < LdapAttribute(String string, DirContext dirContext, Name name) --- > public LdapAttribute(String string, DirContext dirContext, Name name) 57c57 < LdapAttribute(String string, Object object, DirContext dirContext, Name name) --- > public LdapAttribute(String string, Object object, DirContext dirContext, Name name) 65c65 < void setParent(DirContext dirContext, Name name) --- > public void setParent(DirContext dirContext, Name name) 71c71 < private DirContext getBaseCtx() --- > protected DirContext getBaseCtx() 90c90 < private void setBaseCtxInfo() --- > protected void setBaseCtxInfo() ------------------------------------------------------------------------------- ----------- I looked through the code in JavaMembers.java, and saw how the function was located. I wrote my own test program to iterate through the methods and my test program did show the getID() method as public. Therefore, it would have to be something in the code that follows, AFTER my comment in the code. void reflectMethod(Scriptable scope, Method method) { int mods = method.getModifiers(); if (!Modifier.isPublic(mods)) return; // I AM PRESUMING THAT I GET THIS FAR, BUT HAVE NOT CONFIRMED... boolean isStatic = Modifier.isStatic(mods); Hashtable ht = isStatic ? staticMembers : members; String name = method.getName(); NativeJavaMethod fun = (NativeJavaMethod) ht.get(name); if (fun == null) { fun = new NativeJavaMethod(); fun.setParentScope(scope); fun.setPrototype(ScriptableObject.getFunctionPrototype(scope)); ht.put(name, fun); fun.add(method); } else fun.add(method); } So that is as far as I have been able to take it. I sure hope that helps. I have tried this with both the 1.4v3 and 'tip' releaseses of Rhino. Thanks very much for your attention. tim. bugzil> + I used this test case with JDK1.1.7: bugzil> + bugzil> + public class SuperC { bugzil> + public SuperC() {super();} bugzil> + public int pubmeth() {return 7;} bugzil> + static public SubC instantiate() {return new SubC();} bugzil> + } bugzil> + bugzil> + final class SubC extends SuperC { bugzil> + } bugzil> + bugzil> + js> s = Packages.SuperC.instantiate() bugzil> + netscape.javascript.SubC@20684b bugzil> + js> for (p in s) print (p) bugzil> + pubmeth bugzil> + wait bugzil> + notifyAll bugzil> + notify bugzil> + toString bugzil> + equals bugzil> + hashCode bugzil> + getClass bugzil> + js> s.pubmeth() Tim Endres - time@ice.com ICE Engineering, Inc. - http://www.ice.com/ "USENET - a slow moving self parody." - Peter Honeyman
adding frank since it appears this is a rhino issue, not a C engine problem.
Assignee: fur → rogerl
Tim says: Ok, I have a little more input that may mean more to you than it does to me. What I did was go into JavaMembers and add debugging to the methods get() and reflectMethod(). What I see when I run this is that the JavaMembers instance that is called to get() the function is NOT the same as the one that was called to reflectMethod(). On the other hand, when I run the test case that works, the JavaMembers instance is the same in both cases. I have tried to change everything that I can think of in the test app to try and reproduce the problem to no avail. Everytime, the JavaMembers instance remains the same. SO, can anyone think of a reason why the application that fails might cause a different JavaMembers instance to be called for get(), versus the instance that is called for reflectMethod()?! In other words, what is the instance tied to and where does it come from? It appears that the first time is it tied to the javax.naming.directory.BasicAttribute and the second time it is tied to java.lang.Object (based on the "cl" field of JavaMembers). Anyway, here is the output for what it is worth. JMGET is the get() method's output. I have attached the source code with the debugging lines in it so you can make sense of the output. tim. ----------------------------------------------------------------------- ----- COMPILE ----- ----- EXEC ----- // HERE IS THE CALL TO JavaMembers.relectMethod( "getID" )... REFLECTMETHOD: this = 'org.mozilla.javascript.JavaMembers@1cba76 REFLECTMETHOD: cl 'javax.naming.directory.BasicAttribute' = class javax.naming.directory.BasicAttribute REFLECTMETHOD: method getID() = public java.lang.String javax.naming.directory.BasicAttribute.getID() method MODS = 1 isAbstract()? = false isFinal()? = false isInterface()? = false isPrivate()? = false isProtected()? = false isPublic()? = true isStatic()? = false REFLECTMETHOD: FUN = null REFLECTMETHOD: SCOPE '[object Object] REFLECTMETHOD: NEW PUT 'getID', org.mozilla.javascript.NativeJavaMethod@1cb5bd, into {clone=org.mozilla.javascript.NativeJavaMethod@1cb696, wait=org.mozilla.jav ascript.NativeJavaMethod@1cb64b, getClass=org.mozilla.javascript.NativeJavaMetho d@1cb686, hashCode=org.mozilla.javascript.NativeJavaMethod@1cb66a, toString=org. mozilla.javascript.NativeJavaMethod@1cb69a, getID=org.mozilla.javascript.NativeJ avaMethod@1cb5bd, equals=org.mozilla.javascript.NativeJavaMethod@1cb691, size=or g.mozilla.javascript.NativeJavaMethod@1cb659, getAll=org.mozilla.javascript.Nati veJavaMethod@1cb651, notify=org.mozilla.javascript.NativeJavaMethod@1cb643, get= org.mozilla.javascript.NativeJavaMethod@1cb63f, notifyAll=org.mozilla.javascript .NativeJavaMethod@1cb647} ATTR isa com.sun.jndi.ldap.LdapAttribute // HERE IS THE CALL TO JavaMembers.get( "getID" )... JMGET: this = 'org.mozilla.javascript.JavaMembers@1d2425 JMGET: cl 'java.lang.Object' = class java.lang.Object JMGET: scope 'org.mozilla.javascript.NativeJavaObject@1d2422' JMGET: name 'getID' JMGET: ht '{wait=org.mozilla.javascript.NativeJavaMethod@1d2158, getClass=org.mo zilla.javascript.NativeJavaMethod@1d210f, hashCode=org.mozilla.javascript.Native JavaMethod@1d2113, toString=org.mozilla.javascript.NativeJavaMethod@1d2122, equa ls=org.mozilla.javascript.NativeJavaMethod@1d2117, notify=org.mozilla.javascript .NativeJavaMethod@1d2133, notifyAll=org.mozilla.javascript.NativeJavaMethod@1d21 54}' JMGET: member 'null' Exception occurred during event dispatching: org.mozilla.javascript.EvaluatorException: undefined is not a function. at org.mozilla.javascript.DefaultErrorReporter.runtimeError(DefaultErrorReporter.j ava:44) at org.mozilla.javascript.Context.reportRuntimeError(Context.java:390) at org.mozilla.javascript.Context.reportRuntimeError(Context.java:406) at org.mozilla.javascript.ScriptRuntime.call(ScriptRuntime.java:1222) at org.mozilla.javascript.Interpreter.interpret(Interpreter.java:1597) at org.mozilla.javascript.InterpretedScript.call(InterpretedScript.java: ----------------------------------------------------------------------- FOR REFERENCE, THIS IS THE OUTPUT OF THE PROGRAM THAT WORKS OK ----------------------------------------------------------------------- REFLECTMETHOD: this = 'org.mozilla.javascript.JavaMembers@1d1874 REFLECTMETHOD: cl 'com.sun.jndi.ldap.LdapAttribute' = class com.sun.jndi.ldap.LdapAttribute REFLECTMETHOD: method getID() = public java.lang.String javax.naming.directory.BasicAttribute.getID() method MODS = 1 isAbstract()? = false isFinal()? = false isInterface()? = false isPrivate()? = false isProtected()? = false isPublic()? = true isStatic()? = false REFLECTMETHOD: FUN = null REFLECTMETHOD: SCOPE '[object Object] REFLECTMETHOD: NEW PUT 'getID', org.mozilla.javascript.NativeJavaMethod@1d1769, into {clone=org.mozilla.javascript.NativeJavaMethod@1d17ff, wait=org.mozilla.jav ascript.NativeJavaMethod@1d180f, getClass=org.mozilla.javascript.NativeJavaMetho d@1d17f3, hashCode=org.mozilla.javascript.NativeJavaMethod@1d17f7, toString=org. mozilla.javascript.NativeJavaMethod@1d1803, getID=org.mozilla.javascript.NativeJ avaMethod@1d1769, equals=org.mozilla.javascript.NativeJavaMethod@1d17fb, size=or g.mozilla.javascript.NativeJavaMethod@1d17c8, getAll=org.mozilla.javascript.Nati veJavaMethod@1d1815, notify=org.mozilla.javascript.NativeJavaMethod@1d1807, get= org.mozilla.javascript.NativeJavaMethod@1d1819, notifyAll=org.mozilla.javascript .NativeJavaMethod@1d180b} JMGET: this = 'org.mozilla.javascript.JavaMembers@1d1874 JMGET: cl 'com.sun.jndi.ldap.LdapAttribute' = class com.sun.jndi.ldap.LdapAttribute JMGET: scope 'org.mozilla.javascript.NativeJavaObject@1d1873' JMGET: name 'getID' JMGET: ht '{hashCode=org.mozilla.javascript.NativeJavaMethod@1d17f7, remove=org. mozilla.javascript.NativeJavaMethod@1d16ae, clone=org.mozilla.javascript.NativeJ avaMethod@1d17ff, size=org.mozilla.javascript.NativeJavaMethod@1d17c8, getID=org .mozilla.javascript.NativeJavaMethod@1d1769, clear=org.mozilla.javascript.Native JavaMethod@1d16b2, getAll=org.mozilla.javascript.NativeJavaMethod@1d1815, wait=o rg.mozilla.javascript.NativeJavaMethod@1d180f, getAttributeSyntaxDefinition=org. mozilla.javascript.NativeJavaMethod@1d16b9, notify=org.mozilla.javascript.Native JavaMethod@1d1807, toString=org.mozilla.javascript.NativeJavaMethod@1d1803, cont ains=org.mozilla.javascript.NativeJavaMethod@1d16a6, add=org.mozilla.javascript. NativeJavaMethod@1d16aa, notifyAll=org.mozilla.javascript.NativeJavaMethod@1d180 b, getAttributeDefinition=org.mozilla.javascript.NativeJavaMethod@1d16bd, get=or g.mozilla.javascript.NativeJavaMethod@1d1819, getClass=org.mozilla.javascript.Na tiveJavaMethod@1d17f3, equals=org.mozilla.javascript.NativeJavaMethod@1d17fb}' JMGET: member 'org.mozilla.javascript.NativeJavaMethod@1d1769'
Status: NEW → ASSIGNED
The JavaMembers object that is used to perform the 'get' method is a field stored in the NativeJavaObject that wraps the java object itself. This is (or should be) the same value stored in the JavaMembers classTable Hashtable for the class of the object. However, the debug info provided makes it look as if the unwrapped java object is a java.lang.Object instead of the expected one. Can you describe further the process by which the SubC instance is created and the pubmeth() method invoked? I'm suspecting that we're losing the class type info somewhere rather than LC mishandling the reflection. It sure would be nice to have a reproducible case of this, any chance of getting that?
Target Milestone: M13 → M14
Not going to make M13 for these.
Punt.
Target Milestone: M14 → M15
Updating QA Contact
QA Contact: cbegle → rginda
This doesn't seem to be a blocker for the M15 stability checkpoint. Pushing to M16 to facilitate M15 branching.
Target Milestone: M15 → M16
Summary: Public methods are lost when subclassed with a "non-public" class. → Rhino : Public methods are lost when subclassed with a "non-public" class.
Target Milestone: M16 → M30
[SPAM] Bug triage for nsbeta3
Target Milestone: M30 → Future
Comment #7 targets Milestone M13, Comment #10 pushes this to Milestone M16.... Since then activities seem pretty limited. Is this still a valid bug?
-> default assignee for old netscape assigned bugs.
Assignee: rogerl → live-connect
Status: ASSIGNED → NEW
QA Contact: rginda → pschwartau
Target Milestone: Future → ---
Product: Core → Core Graveyard
Firefox code moved from custom Liveconnect code to the NPAPI/NPRuntime bridge a while back. Mass-closing the bugs in the liveconnect component which are likely invalid. If you believe that this bug is still relevant to modern versions of Firefox, please reopen it and move it the "Core" product, component "Plug-Ins".
Status: NEW → RESOLVED
Closed: 14 years ago
Resolution: --- → INCOMPLETE
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: