JDK-4508780 : atg is broken in build 81
  • Type: Bug
  • Component: client-libs
  • Sub-Component: java.beans
  • Affected Version: 1.4.0
  • Priority: P1
  • Status: Closed
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2001-09-28
  • Updated: 2009-11-17
  • Resolved: 2001-11-07
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other
1.4.0 rc1Fixed
Related Reports
Relates :  
Description
With Merlin b81, atg failed on solaris and linux platforms with both -server and -client flags.
errors in atgserver.log file:
javax.servlet.ServletException: atg.droplet.DropletResou
rces->dropletDescriptorIllegalArgGet : Illegal argument trying to get value of P
ersonBean.infoState

1. I replaced libjvm.so with build 80's libjvm.so and retested with -Xint flag,
atg still failed in the same way.
2. I replaced rt.jar with b80's rt.jar, atg runs well.

That proves that the problem is in jdk (rt.jar), not in hotspot(libjvm.so)

I have attached atgserver.log file in the bug report.

How to run atg:
1. telnet to machine jtgb4u2c
2. export JAVA_HOME=<jdk installation>
3. /bs/runatg.ksh -server ( or -client, or -Xint ...)
4. log files are under /bt
check atgserver.log file. 

Note: please do not use /usr/j2se_b81 on jtgb4u2c, rt.jar file is not
the original one from b81. If you need to reinstall jdk on the machine,
please contact me.

###@###.### 2001-09-28


On x86 (machine jtg-i110) , replace build 81's rt.jar with build 80's rt.jar and retest. atg has no immediate failure with -server flag.
However on sparc (machine jtgb4u2c), the trick will not work with -server flag. 
with -client flag , there is no immediate error with build 80' rt.jar

###@###.### 2001-10-01

Yesterday I tried with # of THREADS=1 (export THREADS=${THREADS:=1}, and atg
passed a few iterations with merlin b83. The # of COUNTS, whether set to 1 or 100,  does not cause any difference. When I set # of THREADS=2, atg began to fail.

###@###.### 2001-10-18

I checked back our bigapps log, we did not test build 80 because we were
requested to test engineering build. 
The last time atg passed was with build 79.

 
###@###.### 2001-10-18

I tried b80 for a few iterations with -server on Solaris Sparc, did not
find problem.

###@###.### 2001-10-18

Comments
CONVERTED DATA BugTraq+ Release Management Values COMMIT TO FIX: generic merlin-rc1 FIXED IN: merlin-rc1 INTEGRATED IN: merlin-rc1 VERIFIED IN: merlin-rc1
14-06-2004

EVALUATION Description of bug states that using b80's rt.jar ands all is well. I suspect something putback between b80 <> b81 broke the bigapp ATG. ###@###.### 2001-10-01 Concur, but I'm not sure what. I don't see a smoking gun in the attached log file. A IllegalArgumentException is thrown. Someone who has the source code needs to investigate this, and then move this bug to the appropriate team. ###@###.### 2001-10-01 Email from ###@###.###: ----- I replaced Introspector.class in java/beans with the one from build 80's and kept other classes and packages the same. On x86, with -server flag, There is no immediate failure. (did not try -client) On sparc, with -client flag, There is no immediate failure. However with -server flag, atg still throws "Illegal Argument" exception. ----- Due to the findings, I'm going to move this bug, it appears to be C2 on Sparc with java.beans.Introspector.class from build 81 causing this failure. ###@###.### 2001-10-03 This test fails in -Xint, so it is not a C2 failure. We are looking into the reported failure with the old library, but there is clearly a problem with the new library. ###@###.### 2001-10-05 =================================================== This problem exists in the PersonDemo located at /net/jtgb4u4c/export/sail8/1.3bigapps/ws/master/dist/atg/Dynamo4.5.0/doc/demo/PersonDemo/ The problem seems to occur after /demo/PersonDemo/PersonInfo.jhtml to ./pagebuild/_doc_3/_demo/_PersonDemo/_PersonInfo.java is compiled. An abridged output of the log is as follows: **** Error /atg/dynamo/server/HttpServer --- javax.servlet.ServletException: atg.droplet.DropletResources->dropletDescriptorIllegalArgGet : Illegal argument trying to get value of PersonBean.infoState --- javax.servlet.ServletException: atg.droplet.DropletResources->dropletDescriptorIllegalArgGet : Illegal argument trying to get value of PersonBean.infoState at atg.droplet.DropletDescriptor.getPropertyValue(DropletDescriptor.java:485) at atg.droplet.DropletDescriptor.getPropertyValue(DropletDescriptor.java:577) at _doc_3._demo._PersonDemo._Person.service(_Person.java:418) at atg.servlet.DynamoServlet.service(DynamoServlet.java:120) at atg.servlet.pagecompile.PageCompileServlet.service(PageCompileServlet.java:284) at atg.servlet.DynamoServlet.service(DynamoServlet.java:120) at atg.servlet.pagecompile.SubServlet.serviceServlet(SubServlet.java:211) at atg.servlet.pagecompile.SubServlet.service(SubServlet.java:137) at _doc_3._demo._PersonDemo._index.service(_index.java:62) ....stack trace CROPPED after 10 lines. --- java.lang.IllegalArgumentException: java.lang.IllegalArgumentException: java.lang.ClassCastException@c3e82b: Attempting to call public void PersonBean.setUserName(java.lang.String) with value jjv class = class java.lang.String at atg.droplet.EventSender.sendEvent(EventSender.java:456) at atg.droplet.FormTag.doSendEvents(FormTag.java:586) at atg.droplet.FormTag.sendEvents(FormTag.java:491) at atg.droplet.DropletEventServlet.sendEvents(DropletEventServlet.java:190) at atg.droplet.DropletEventServlet.service(DropletEventServlet.java:209) at atg.servlet.pipeline.PipelineableServletImpl.service(PipelineableServletImpl.java:224) at atg.servlet.pipeline.DispatcherPipelineServletImpl.service(DispatcherPipelineServletImpl.java:146) at atg.servlet.pipeline.PipelineableServletImpl.passRequest(PipelineableServletImpl.java:114) at atg.servlet.pipeline.MimeTyperPipelineServlet.service(MimeTyperPipelineServlet.java:167) ....stack trace CROPPED after 10 lines. gument --- java.lang.IllegalArgumentException: java.lang.IllegalArgumentException: java.lang.ClassCastException@2b349d: Attempting to call public void PersonBean.setAvaconURL(java.lang.String) with value broken image class = class java.lang.String at atg.droplet.EventSender.sendEvent(EventSender.java:456) at atg.droplet.FormTag.doSendEvents(FormTag.java:586) at atg.droplet.FormTag.sendEvents(FormTag.java:491) at atg.droplet.DropletEventServlet.sendEvents(DropletEventServlet.java:190) at atg.droplet.DropletEventServlet.service(DropletEventServlet.java:209) at atg.servlet.pipeline.PipelineableServletImpl.service(PipelineableServletImpl.java:224) at atg.servlet.pipeline.DispatcherPipelineServletImpl.service(DispatcherPipelineServletImpl.java:146) at atg.servlet.pipeline.PipelineableServletImpl.passRequest(PipelineableServletImpl.java:114) at atg.servlet.pipeline.MimeTyperPipelineServlet.service(MimeTyperPipelineServlet.java:167) ....stack trace CROPPED after 10 lines. The jhtml files are translated to java in the atgrun pagebuild directory: /bt/atgrun.8213./pagebuild/_doc_3/_demo/_PersonDemo Specifically, the line 418 line in _Person.java in the method service() seems to be the method thats failing first: request.setParameter("value", DropletDescriptor.getPropertyValue(request, response, "PersonBean.infoState", true, null, null)); DropletDescriptor was decompiled and there seems to be some sort of dynamic property mapper architecture. It seems to me that the problem is an IllegalArgumentException which has been caught from Method.invoke(). I'm beginning to believe that the problem may not lie in the changes to the Introspector. I have included a TestPersonBean which uses the 1.4 Introspector to execute every single getter method in the array of returned PropertyDescriptors from the PersonBean. Unfortunately, the ATG architecture seems to rewrite the entire java.beans. package. The set of PropertyDescriptors, MethodDecriptors and EventSetDescriptors seem to be identical for PersonBean between b80 and b82. I reverted my changes to getTargetEventInfo() in which I used the cached version of the public declared methods for a class. Unfortunately, that *didn't* solve the problem. I've just reverted the method cache key in the Introspector to use the class instead of class.getName(). I doubt that that will fix the problem but I've submitted the classes to Jun Z for testing. Some helpful directories: All the output from the servlet jhtml -> java: /home/davidson/bug_tests/beans/Introspector/450878/pagebuild JAD decompiled classes that were under investigation: /home/davidson/bug_tests/beans/Introspector/450878/jad ###@###.### 2001-10-08 I'm becoming much more convinced that the problem is not really in the Introspector. I re-ran my TestPersonBean with java -server and didn't see any problem with reflective method invocation. Also, reverting the Introspector to the classes in b80 doens't fix the problem on Solaris Sparc with C2. We performed a run with a hacked version of DropletDescriptor to show the stack trace of the caught IllegalArgumentException and my assertion was correct. The Method.invoke() method call is the source of the exception: The first exception encountered is from getting the value of PersonBean.infoState: DropletDescriptor: IllegalArgumentException thrown: java.lang.ClassCastException@bf1d3b java.lang.IllegalArgumentException: java.lang.ClassCastException@bf1d3b at sun.reflect.GeneratedMethodAccessor14.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:28) at java.lang.reflect.Method.invoke(Method.java:327) at atg.droplet.DropletDescriptor.getPropertyValue(DropletDescriptor.java:586) at atg.droplet.DropletDescriptor.getPropertyValue(DropletDescriptor.java:639) at _doc_3._demo._PersonDemo._Person.service(_Person.java:418) at atg.servlet.DynamoServlet.service(DynamoServlet.java:120) Similar exceptions are thrown by setting exectuting the setter methods within the context of atg.droplet.EventSender.sendEvent(). This also uses the Relective method invocation on the setter method I've decompiled the EventSender class and flaged the failure points with XXX. boolean sendEvent(DynamoHttpServletRequest dynamohttpservletrequest, DynamoHttpServletResponse dynamohttpservletresponse, EventReceiver eventreceiver, Object aobj[], Vector vector) throws DropletException, ServletException, IOException ... // XXX -- this is a problem. The obj4 has a value like "broken image", "jjv", // "El nino makes sunnydale not" throw new IllegalArgumentException(illegalargumentexception1.toString() + ": Attempting to call " + dropletdescriptor.setMethod + " with value " + obj4 + " class = " + obj4.getClass()); The summary of the failures produced by this method include: java.lang.IllegalArgumentException: java.lang.IllegalArgumentException: java.lang.ClassCastException@4b6bed: Attempting to call public void PersonBean.setUserName(java.lang.String) with value "jjv" class = class java.lang.String java.lang.IllegalArgumentException: java.lang.IllegalArgumentException: java.lang.ClassCastException@6db724: Attempting to call public void PersonBean.setAvaconURL(java.lang.String) with value "broken image" class = class java.lang.String java.lang.IllegalArgumentException: java.lang.IllegalArgumentException: java.lang.ClassCastException@412e75: Attempting to call public void PersonBean.setMessage(java.lang.String) with value "El nino makes sunnydale not" class = class java.lang.String java.lang.IllegalArgumentException: java.lang.IllegalArgumentException: java.lang.ClassCastException@650892: Attempting to call public void PersonBean.setMessage(java.lang.String) with value "A different less stupid message" class = class java.lang.String I've added quotes to the values to make them more obvious. Even though these classes are from the PersonDemo in ../Dynamo4.5.0/doc/demo/PersonDemo, I can't seem to find the values for this data. Perhaps there is an initialization problem? The strange thing is that according to the diagnostics all these are valid values and valid types. I've included a zip file, droplet.zip, which includes the sources for DropletDescriptor (executes the getter method) and EventSender (executes the setter method) and the build.sh file to compile them. You may want to add diagnostics to these classes and prepend them to the classpath to figure out what's going on. ------------------------ Regarding the ClassCastException from Ken Russell: If the problem occurs with -Xint then it is likely not a C2 bug. I still think this is unlikely to be a bug in the reflection code as it did not change in B81. The portion of the bytecode generator which is turning the ClassCastException into an IllegalArgumentException is in the Merlin workspace in src/share/classes/sun/reflect/MethodAccessorGenerator.java, line 668. More bytecodes could be inserted to get more information out of the ClassCastException; currently toString() is being called upon it and is being passed as the detail message for the IllegalArgumentException, but more detail would be useful as we still don't know what object was passed in to cause one of the generated checkcasts to fail. (Alternatively, the ClassCastException conversion could be elided and the ClassCastException allowed to propagate out of the Method.invoke() temporarily, and printStackTrace() called from the DropletDescriptor.) A revised MethodAccessorGenerator can easily be prepended to the boot class path with -Xbootclasspath/p:<directory name>. In particular, one could make the following change: // ClassCast, etc. exception handler cb.setStack(1); // cb.opc_invokespecial(toStringIdx, 0, 1); // cb.opc_new(illegalArgumentClass); // cb.opc_dup_x1(); // cb.opc_swap(); // cb.opc_invokespecial(illegalArgumentStringCtorIdx, 1, 0); cb.opc_athrow(); and now the ClassCastException will be propagated out of Method.invoke(). ---------------------------------------------------------- I'm going to hand it over to hotspot/compiler2 for more analysis. Feel free to contact me if you need any aditional help or information. ###@###.### 2001-10-10 ------------------------- The problem is confirmed to be multiple classloaders getting at the shared data in the Introspector. Part of the problem is that there are static HashMaps which are being used for caches but the key is the name of the class rather than the class itself. The name of a class does not uniquely identify that class when using multiple class loaders. The methods that were cached in the Introspector method cache belonged to an instance of a class loaded with one class loader and were accessed with a different class loader. When the methods were reflectively invoked, a ClassCastException/IllegalArgumentException was thrown. I've sucessfully, reproduced the ATG bug with a small test case which accesses the Introspector on multiple threads with multiple instances of ClassLoaders. I'm also seeing the race conditions which exist (and would fail 20% of the time) before the changes in b81. Moving forward, the solution is to use Soft references to the classes as the HashMap keys. ###@###.### 2001-10-22
22-10-2001