ClassCostException in FunctionObject static initializer

VERIFIED FIXED in 1.5R4

Status

Rhino
Core
VERIFIED FIXED
16 years ago
14 years ago

People

(Reporter: Leonid Kuoza, Assigned: Norris Boyd)

Tracking

other
1.5R4
x86
Windows 2000

Details

Attachments

(1 attachment, 1 obsolete attachment)

(Reporter)

Description

16 years ago
When I run unit tests that use rhino in JUnit GUI test tunner I receive the 
following exception:

java.lang.ExceptionInInitializerError: java.lang.ClassCostException: 
org.mozilla.javascript.optimizer.InvokerImpl
  at org.mozilla.javascript.javascript.FunctionObject.newInvokerMaster(Unknown 
Source)
  ...

When I run it in JUnit text test runner, it works OK.

I believe that it is because GUI JUnit uses its own class loader and Rhino uses 
its own.

The following test case might be used to reproduce bug:


package com.actimind.watf;

import junit.framework.*;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.Scriptable;

public class RhinoTest extends TestCase
{
    public RhinoTest( String s )
    {
        super( s );
    }

    public void testRhino()
    {
        Context context = Context.enter();
        try
        {
            Scriptable scope = context.initStandardObjects( null );
        }
        finally
        {
            context.exit();
        }
    }
}


Just run this in GUI JUnit test runner, and see what happens.

I use Rhino 1.5R3

Comment 1

15 years ago
Created attachment 110302 [details] [diff] [review]
To search in DefiningClassLoader.loadClass(String name, boolean resolve) for classes not defined by the class loader itself use parent loader, not the one obtained via Thread.getContextClassLoader()

Various parts of Rhino need to define classes based on generated code and for
that they use org.mozilla.classfile.DefiningClassLoader. Currently its
DefiningClassLoader.loadClass(String name, boolean resolve) method when
searches for a class not defined by the loader itself calls
Thread.getContextClassLoader() on the assumption that an application may call
Thread.setContextClassLoader() to alter class loader for a particular thread. 

By default Thread.getContextClassLoader() returns the system classes loader and
if Rhino classes are not loaded through it, then any reference to a Rhino class
from the generated byte code would either lead to ClassNotFoundException or if
a copy of Rhino is available on the system loader to ClassCastException later
as in JVM classes with the same name but different class loaders are treated as
different classes. The later case I believe is the reason for the reported
error.

To resolve the issue, the patch changes DefiningClassLoader.loadClass to look
for a class from the parent class loader, which points to the loader that loads
Rhino classes and this is what necessary in all cases involving
DefiningClassLoader usage.

Comment 2

15 years ago
Created attachment 110304 [details] [diff] [review]
Small fix to the previous version: the parentLoader field should be private
Attachment #110302 - Attachment is obsolete: true

Comment 3

15 years ago
I committed the above patch with few other changes to replace calls to
Thread.getContextClassLoader() by using a proper parent class loader for
generated code. This fixed I believe a similar problem reported by Mike Gillam
as he confirmed that after the changes the following is no longer an issue:

Mike Gillam <mgillam@attbi.com> wrote to netsacpe.public.mozilla.jseng:
...
I am using Rhino to script business objects implemented within an EJB
Session object.

Everything works fine until I redeploy the .EAR file.  After
redeployment, none of the methods I expose in the ScriptableObject
classes work.  I get a ClassCastException.
...

 org.mozilla.javascript.JavaScriptException:
java.lang.ClassCastException
 	at
org.mozilla.javascript.JavaScriptException.wrapException(JavaScriptException.java:69)
 	at org.mozilla.javascript.FunctionObject.call(FunctionObject.java:439)
 	at org.mozilla.javascript.ScriptRuntime.call(ScriptRuntime.java:1225)
 	at
org.mozilla.javascript.gen.c85.call(IDBE_Pricing_Policy::SIZE_CRUST::IDV_Pricing_Formula:2)
 	at com.moose.bos.BusinessRule.execute(BusinessRule.java:88)
 	at com.moose.erp.PricingPolicy.price(PricingPolicy.java:88)
 	at com.moose.erp.ItemHasPrice.price(ItemHasPrice.java:106)
 	at com.moose.erp.Attribute.price(Attribute.java:225)
 	at
com.moose.erp.ItemHasAttributes.describeConfiguration(ItemHasAttributes.java:186)
 	at com.moose.erp.Item.configure(Item.java:245)
 	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
 	at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
 	at java.lang.reflect.Method.invoke(Method.java:324)
 	at com.moose.bos.BusinessObj.callCommand(BusinessObj.java:69)
 	at com.moose.bos.BusinessObj.process(BusinessObj.java:488)
 	at com.moose.bos.Entity.process(Entity.java:1507)
 	at com.moose.bos.BusinessObj.processMessage(BusinessObj.java:574)
 	at com.moose.bos.Server.processMessage(Server.java:973)
 	at com.moose.bos.Server.processExternalMessage(Server.java:865)
 	at com.moose.ejb.BOSSessionStatelessBean.process(BOSSessionStatelessBean.java:125)
 	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
 	at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
 	at java.lang.reflect.Method.invoke(Method.java:324)
 	at
org.jboss.ejb.StatelessSessionContainer$ContainerInterceptor.invoke(StatelessSessionContainer.java:664)
 	at
org.jboss.resource.connectionmanager.CachedConnectionInterceptor.invoke(CachedConnectionInterceptor.java:186)
 	at
org.jboss.ejb.plugins.AbstractTxInterceptor.invokeNext(AbstractTxInterceptor.java:96)
 	at
org.jboss.ejb.plugins.AbstractTxInterceptorBMT.invokeNext(AbstractTxInterceptorBMT.java:144)
 	at org.jboss.ejb.plugins.TxInterceptorBMT.invoke(TxInterceptorBMT.java:62)
 	at
org.jboss.ejb.plugins.StatelessSessionInstanceInterceptor.invoke(StatelessSessionInstanceInterceptor.java:77)
 	at org.jboss.ejb.plugins.SecurityInterceptor.invoke(SecurityInterceptor.java:129)
 	at org.jboss.ejb.plugins.LogInterceptor.invoke(LogInterceptor.java:166)
 	at
org.jboss.ejb.StatelessSessionContainer.invoke(StatelessSessionContainer.java:313)
 	at org.jboss.ejb.Container.invoke(Container.java:705)
 	at org.jboss.mx.server.MBeanServerImpl.invoke(MBeanServerImpl.java:491)
 	at org.jboss.invocation.local.LocalInvoker.invoke(LocalInvoker.java:98)
 	at org.jboss.invocation.InvokerInterceptor.invoke(InvokerInterceptor.java:102)
 	at org.jboss.proxy.TransactionInterceptor.invoke(TransactionInterceptor.java:73)
 	at org.jboss.proxy.SecurityInterceptor.invoke(SecurityInterceptor.java:76)
 	at
org.jboss.proxy.ejb.StatelessSessionInterceptor.invoke(StatelessSessionInterceptor.java:111)
 	at org.jboss.proxy.ClientContainer.invoke(ClientContainer.java:76)
 	at $Proxy29.process(Unknown Source)
 	at com.moose.servlet.BOSSrvlet.callBOS(BOSSrvlet.java:108)
 	at
com.moose.servlet.ConfiguratorServlet.buildConfigFrame(ConfiguratorServlet.java:269)
etc.....

Comment 4

15 years ago
Marking FIXED -
Status: NEW → RESOLVED
Last Resolved: 15 years ago
Resolution: --- → FIXED

Comment 5

15 years ago
Tentatively marking Verified; Leonid, can you confirm
that the bug is fixed with the latest Rhino source?

If not, you can reopen this bug; thanks -
Status: RESOLVED → VERIFIED

Comment 6

14 years ago
Targeting as resolved against 1.5R4
Target Milestone: --- → 1.5R4
You need to log in before you can comment on or make changes to this bug.