| java.lang.Object org.apache.derby.impl.services.bytecode.BCJava
BCJava | public class BCJava implements JavaFactory,CacheableFactory,ModuleControl(Code) | |
Debugging problems with generated classes
When the code has been generated incorrectly, all sorts of
odd things can go wrong. This is one recommended approach to
finding the problem.
First, turn on ByteCodeGenInstr and DumpClassFile. Look
for missing files (right now they are consecutively numbered
by the activation class builder; later on they won't be, but
BytCodeGenInstr dumps messages about the classes it has).
Look at the log to make sure that all "GEN starting class/method"
messages are paired with a "GEN ending class/method" message.
If a file is missing or the pairing is missing, then something
went wrong when the system tried to generate the bytecodes.
Resort to your favorite debugging tool to step through
the faulty statement.
If you get class files but the system crashes on you (I had
an OS segmentation fault once) or you get funny messages like
JDBC Excpetion: ac5 where ac5 is just the name of a generated
class, then one of the following is likely:
- you are calling INVOKEVIRTUAL when
you are supposed to call INVOKEINTERFACE
- you have an inexact match on a method argument or
return type.
- you are trying to get to a superclass's field using
a subclass.
The best way to locate the problem here is to do this (replace
ac5.class with the name of your class file):
- javap -c -v ac5 >ac5.gp
if javap reports "Class not found", and the file ac5.class does
exist in the current directory, then the .class file is probably
corrupt. Try running mocha on it to see if that works. The
problem will be in the code that generates the entries for
the class file -- most likely the ConstantPool is bad, an
attribute got created incorrectly, or
perhaps the instruction streams are goofed up.
- java mocha.Decompiler ac5.class
if mocha cannot create good java source, then you really
need to go back and examine the calls creating the java
constructs; a parameter might have been null when it should
have, a call to turn an expression into a statement may be
missing, or something else may be wrong.
- mv ac5.mocha ac5.java
- vi ac5.java ; you will have to fix any new SQLBoolean(1, ...)
calls to be new SQLBoolean(true, ...). Also mocha
occasionally messes up other stuff too. Just iterate on it
until it builds or you figure out what is wrong with
the generated code.
- javac ac5.java
- javap -v -c ac5 >ac5.jp
- sed '1,$s/#[0-9]* # ' ac5.gp > ac5.gn
- sed '1,$s/#[0-9]* # ' ac5.jp > ac5.jn
These seds are to get rid of constant pool entry numbers,
which will be wildly different on the two files.
- vdiff32 ac5.gn ac5.jn
this tool shows you side-by-side diffs. If you change
to the window that interleaves the diffs, you can see the
length of the line. Look for places where there are
invokevirtual vs. invokeinterface differences, differences
in the class name of a field, differences in the class name
of a method parameter or return type. The generated code
will* have some unavoidable differences from the
compiled code, such as:
- it will have goto's at the end of try blocks
rather than return's.
- it will do a getstatic on a static final field
rather than inlining the static final field's value
- it will have more checkcast's in it, since it
doesn't see if the checkcast will always succeed
and thus remove it.
Once you find a diff, you need to track down where
the call was generated and modify it appropriately:
change newMethodCall to newInterfaceMethodCall;
add newCastExpression to get a argument into the right
type for the parameter; ensure the return type given for
the method is its declared return type.
See Also: org.apache.derby.iapi.services.compiler.JavaFactory author: ames |
Constructor Summary | |
public | BCJava() |
newClassBuilder | public ClassBuilder newClassBuilder(ClassFactory cf, String packageName, int modifiers, String className, String superClass)(Code) | | a class. Once it is created, fields, methods,
interfaces, static initialization code,
and constructors can be added to it.
Java: package #packageName;
#modifiers #className extends #superClass { }
// modifiers is the | of the JVM constants for
// the modifiers such as static, public, etc.
See java.lang.reflect.Modifiers
Parameters: packageName - the name of the package the class is in.null if it is in the default package. Parameters: modifiers - the | of the Modifiersconstants representing the visibility and control of thismethod. Parameters: className - the name of the class or interface Parameters: superClass - the name of the superclass or superinterface the class builder. |
stop | public void stop()(Code) | | Stop this module. In this case, nothing needs to be done.
|
type | Type type(String javaType)(Code) | | Get the VM Type ID that corresponds with the given java type name.
This uses the cache of VM type ids.
Parameters: javaType - The java type name to translate to a java VM type id The java VM type ID |
vmTypeId | static short vmTypeId(String vmTypeS)(Code) | | Map vm types as strings to vm types as the VM
handles, with int ids. Used in mapping opcodes
based on type of operand/stack entry available.
|
|
|