KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > derby > impl > services > bytecode > BCJava


1 /*
2
3    Derby - Class org.apache.derby.impl.services.bytecode.BCJava
4
5    Licensed to the Apache Software Foundation (ASF) under one or more
6    contributor license agreements. See the NOTICE file distributed with
7    this work for additional information regarding copyright ownership.
8    The ASF licenses this file to you under the Apache License, Version 2.0
9    (the "License"); you may not use this file except in compliance with
10    the License. You may obtain a copy of the License at
11
12       http://www.apache.org/licenses/LICENSE-2.0
13
14    Unless required by applicable law or agreed to in writing, software
15    distributed under the License is distributed on an "AS IS" BASIS,
16    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17    See the License for the specific language governing permissions and
18    limitations under the License.
19
20  */

21
22 package org.apache.derby.impl.services.bytecode;
23
24 import org.apache.derby.iapi.services.compiler.JavaFactory;
25 import org.apache.derby.iapi.services.compiler.ClassBuilder;
26 import org.apache.derby.iapi.services.compiler.MethodBuilder;
27 import org.apache.derby.iapi.services.loader.ClassFactory;
28 import org.apache.derby.iapi.services.classfile.ClassHolder;
29
30 import org.apache.derby.iapi.services.cache.Cacheable;
31 import org.apache.derby.iapi.services.cache.CacheableFactory;
32
33 import org.apache.derby.iapi.services.cache.CacheFactory;
34 import org.apache.derby.iapi.services.cache.CacheManager;
35
36 import org.apache.derby.iapi.services.monitor.Monitor;
37 import org.apache.derby.iapi.services.monitor.ModuleControl;
38
39 import org.apache.derby.iapi.error.StandardException;
40
41 import org.apache.derby.iapi.services.sanity.SanityManager;
42
43 import org.apache.derby.iapi.services.classfile.VMDescriptor;
44
45 import java.util.Properties JavaDoc;
46 import java.util.Hashtable JavaDoc;
47
48 /**
49     <p>
50     <b>Debugging problems with generated classes</b>
51     <p>
52     When the code has been generated incorrectly, all sorts of
53     odd things can go wrong. This is one recommended approach to
54     finding the problem.
55     <p>
56     First, turn on ByteCodeGenInstr and DumpClassFile. Look
57     for missing files (right now they are consecutively numbered
58     by the activation class builder; later on they won't be, but
59     BytCodeGenInstr dumps messages about the classes it has).
60     Look at the log to make sure that all "GEN starting class/method"
61     messages are paired with a "GEN ending class/method" message.
62     If a file is missing or the pairing is missing, then something
63     went wrong when the system tried to generate the bytecodes.
64     Resort to your favorite debugging tool to step through
65     the faulty statement.
66     <p>
67     If you get class files but the system crashes on you (I had
68     an OS segmentation fault once) or you get funny messages like
69     JDBC Excpetion: ac5 where ac5 is just the name of a generated
70     class, then one of the following is likely:
71     <ul>
72     <li> you are calling INVOKEVIRTUAL when
73          you are supposed to call INVOKEINTERFACE
74     <li> you have an inexact match on a method argument or
75          return type.
76     <li> you are trying to get to a superclass's field using
77          a subclass.
78     </ul>
79     The best way to locate the problem here is to do this (replace
80     ac5.class with the name of your class file):
81     <ol>
82     <li> javap -c -v ac5 >ac5.gp<br>
83          if javap reports "Class not found", and the file ac5.class does
84          exist in the current directory, then the .class file is probably
85          corrupt. Try running mocha on it to see if that works. The
86          problem will be in the code that generates the entries for
87          the class file -- most likely the ConstantPool is bad, an
88          attribute got created incorrectly, or
89          perhaps the instruction streams are goofed up.
90     <li> java mocha.Decompiler ac5.class<br>
91          if mocha cannot create good java source, then you really
92          need to go back and examine the calls creating the java
93          constructs; a parameter might have been null when it should
94          have, a call to turn an expression into a statement may be
95          missing, or something else may be wrong.
96     <li> mv ac5.mocha ac5.java
97     <li> vi ac5.java ; you will have to fix any new SQLBoolean(1, ...)
98          calls to be new SQLBoolean(true, ...). Also mocha
99          occasionally messes up other stuff too. Just iterate on it
100          until it builds or you figure out what is wrong with
101          the generated code.
102     <li> javac ac5.java
103     <li> javap -v -c ac5 >ac5.jp
104     <li> sed '1,$s/#[0-9]* </# </' ac5.gp > ac5.gn
105     <li> sed '1,$s/#[0-9]* </# </' ac5.jp > ac5.jn<br>
106          These seds are to get rid of constant pool entry numbers,
107          which will be wildly different on the two files.
108     <li> vdiff32 ac5.gn ac5.jn<br>
109          this tool shows you side-by-side diffs. If you change
110          to the window that interleaves the diffs, you can see the
111          length of the line. Look for places where there are
112          invokevirtual vs. invokeinterface differences, differences
113          in the class name of a field, differences in the class name
114          of a method parameter or return type. The generated code
115          *will* have some unavoidable differences from the
116          compiled code, such as:
117          <ul>
118          <li> it will have goto's at the end of try blocks
119           rather than return's.
120          <li> it will do a getstatic on a static final field
121           rather than inlining the static final field's value
122          <li> it will have more checkcast's in it, since it
123           doesn't see if the checkcast will always succeed
124           and thus remove it.
125          </ul>
126          Once you find a diff, you need to track down where
127          the call was generated and modify it appropriately:
128          change newMethodCall to newInterfaceMethodCall;
129          add newCastExpression to get a argument into the right
130          type for the parameter; ensure the return type given for
131          the method is its declared return type.
132     </ol>
133     @see org.apache.derby.iapi.services.compiler.JavaFactory
134
135     @author ames
136  */

137 public class BCJava implements JavaFactory, CacheableFactory, ModuleControl {
138
139     //////////////////////////////////////////////////////////////
140
//
141
// MEMBERS
142
//
143
//////////////////////////////////////////////////////////////
144

145     /* Cache of Java class names versus VM type names */
146     private CacheManager vmTypeIdCache;
147
148     //
149
// class interface
150
//
151
public BCJava() {
152     }
153
154     //
155
// ModuleControl interface
156
//
157
/**
158         Start this module. We need a read/write version of the class utilities
159
160         @exception StandardException standard cloudscape policy
161      */

162     public void boot(boolean create, Properties JavaDoc properties) throws StandardException {
163
164         CacheFactory cf =
165             (CacheFactory) Monitor.startSystemModule(org.apache.derby.iapi.reference.Module.CacheFactory);
166
167         /*
168         ** The initial and maximum cache sizes are based on experiments
169         ** that I did with some of the language tests. I found that
170         ** the size quickly grew to about 40, then continued to grow
171         ** slowly after that.
172         **
173         ** - Jeff
174         */

175         vmTypeIdCache =
176             cf.newCacheManager(
177                 this,
178                 "VMTypeIdCache",
179                 64,
180                 256);
181     }
182
183     /**
184         Stop this module. In this case, nothing needs to be done.
185      */

186     public void stop() {
187     }
188
189     //
190
// JavaFactory interface
191
//
192

193     /**
194      * a class. Once it is created, fields, methods,
195      * interfaces, static initialization code,
196      * and constructors can be added to it.
197      * <verbatim>
198        Java: package #packageName;
199          #modifiers #className extends #superClass { }
200             // modifiers is the | of the JVM constants for
201             // the modifiers such as static, public, etc.
202        </verbatim>
203      *
204      * See java.lang.reflect.Modifiers
205      * @param packageName the name of the package the class is in.
206      * null if it is in the default package.
207      * @param modifiers the | of the Modifiers
208      * constants representing the visibility and control of this
209      * method.
210      * @param className the name of the class or interface
211      * @param superClass the name of the superclass or superinterface
212      *
213      * @return the class builder.
214      */

215     public ClassBuilder newClassBuilder(ClassFactory cf, String JavaDoc packageName,
216         int modifiers, String JavaDoc className, String JavaDoc superClass) {
217         
218         return new BCClass(cf, packageName, modifiers, className, superClass, this);
219     }
220
221     /*
222     ** CacheableFactory interface
223     */

224     public Cacheable newCacheable(CacheManager cm) {
225         return new VMTypeIdCacheable();
226     }
227
228     ///////////////////////////////////////////
229
//
230
// UTILITIES specific to this implementation
231
//
232
////////////////////////////////////////////
233

234     /**
235      * Get the VM Type ID that corresponds with the given java type name.
236      * This uses the cache of VM type ids.
237      *
238      * @param javaType The java type name to translate to a java VM type id
239      *
240      * @return The java VM type ID
241      */

242     Type type(String JavaDoc javaType) {
243
244         Type retval;
245
246         try {
247
248             VMTypeIdCacheable vtic = (VMTypeIdCacheable) vmTypeIdCache.find(javaType);
249
250             retval = (Type) vtic.descriptor();
251
252             vmTypeIdCache.release(vtic);
253
254             return retval;
255
256         } catch (StandardException se) {
257             if (SanityManager.DEBUG) {
258                 SanityManager.THROWASSERT("Unexpected exception " + se, se);
259             }
260
261             /*
262             ** If we're running a sane server, let's act as if the
263             ** exception didn't happen, and just get the vmTypeId the
264             ** slow way, without caching.
265             */

266             retval = new Type(javaType, ClassHolder.convertToInternalDescriptor(javaType));
267         }
268
269         return retval;
270     }
271
272     String JavaDoc vmType(BCMethodDescriptor md) {
273         String JavaDoc retval;
274
275         try {
276
277             VMTypeIdCacheable vtic = (VMTypeIdCacheable) vmTypeIdCache.find(md);
278
279             retval = vtic.descriptor().toString();
280
281             vmTypeIdCache.release(vtic);
282
283         } catch (StandardException se) {
284             if (SanityManager.DEBUG) {
285                 SanityManager.THROWASSERT("Unexpected exception " + se, se);
286             }
287
288             /*
289             ** If we're running a sane server, let's act as if the
290             ** exception didn't happen, and just get the vmTypeId the
291             ** slow way, without caching.
292             */

293             retval = md.buildMethodDescriptor();
294         }
295
296         return retval;
297     }
298     /**
299      * Map vm types as strings to vm types as the VM
300      * handles, with int ids. Used in mapping opcodes
301      * based on type of operand/stack entry available.
302      */

303     static short vmTypeId(String JavaDoc vmTypeS) {
304         char vmTypeC = vmTypeS.charAt(0);
305         switch(vmTypeC) {
306             case VMDescriptor.C_CLASS : return BCExpr.vm_reference;
307             case VMDescriptor.C_BYTE : return BCExpr.vm_byte;
308             case VMDescriptor.C_CHAR : return BCExpr.vm_char;
309             case VMDescriptor.C_DOUBLE : return BCExpr.vm_double;
310             case VMDescriptor.C_FLOAT : return BCExpr.vm_float;
311             case VMDescriptor.C_INT : return BCExpr.vm_int;
312             case VMDescriptor.C_LONG : return BCExpr.vm_long;
313             case VMDescriptor.C_SHORT : return BCExpr.vm_short;
314             case VMDescriptor.C_BOOLEAN : return BCExpr.vm_int;
315             case VMDescriptor.C_ARRAY : return BCExpr.vm_reference;
316             case VMDescriptor.C_VOID : return BCExpr.vm_void;
317             default:
318                 if (SanityManager.DEBUG)
319                 SanityManager.THROWASSERT("No type match for "+vmTypeS);
320         }
321         return BCExpr.vm_void;
322     }
323 }
324
Popular Tags