FPC JVM/Debugging: what changed
Revision 0 to 1. Removed lines have a minus sign; added lines have a plus sign.
Title: FPC JVM/Debugging
| Old | New | Line | |
|---|---|---|---|
| 1 | + | # Debugging help | |
| 2 | + | ||
| 3 | + | The compiler does not catch all errors in the source code that may result in invalid JVM bytecode. Examples include uninitialized variables and some invalid typecasts. The consequence is that you will get verification errors from the JVM at run time. | |
| 4 | + | ||
| 5 | + | If the source code is compiled with the -g option, all exception backtraces will contain source line information (except in case of include files, as explained earlier). | |
| 6 | + | ||
| 7 | + | Additionally, even if the bytecode passes the verifier, there can still be logic bugs in your program. | |
| 8 | + | ||
| 9 | + | ## Bytecode verification | |
| 10 | + | ||
| 11 | + | The Apache Commons [BCEL project](http://commons.apache.org/bcel/) includes a very handy JVM byte code verifier. Unfortunately, the current release version (5.2) is quite old and does not support all JDK 1.5 features used by FPC. You have to use the svn version instead. | |
| 12 | + | ||
| 13 | + | ### Download BCEL snapshot | |
| 14 | + | ||
| 15 | + | A prebuilt version of the patched BCEL 6.0 snapshot is included in the [[FPC JVM|snapshots]] and can also be downloaded as part of the [Java-specific utilities](ftp://ftp.freepascal.org/pub/fpc/contrib/jvm/fpcjvmutilities.zip). | |
| 16 | + | ||
| 17 | + | Compilation instructions and a required patch can be found at [[FPC JVM/Building]]. | |
| 18 | + | ||
| 19 | + | ### Running the verifier | |
| 20 | + | ||
| 21 | + | To run the verifier on, e.g., the system unit class *org.freepascal.rtl.system* | |
| 22 | + | ||
| 23 | + | ` java -Xmx1000000000 -cp /full/path/to/bcel/target/bcel-6.0-SNAPSHOT.jar:.:/full/path/to/fpc/rtl/units/jvm-java org.apache.bcel.verifier.Verifier org.freepascal.rtl.System` | |
| 24 | + | ||
| 25 | + | (that is for Unix systems, on Windows replace the forward slashes with backslashes, and separate directories with *;* instead of with *:*). | |
| 26 | + | ||
| 27 | + | On Unix systems, you can create a shell script called *jverify.sh* with the following contents: | |
| 28 | + | ||
| 29 | + | ` #!/bin/sh`\ | |
| 30 | + | ` java -Xmx1000000000 -cp /full/path/to/bcel/target/bcel-6.0-SNAPSHOT.jar:.:/full/path/to/fpc/rtl/units/jvm-java org.apache.bcel.verifier.Verifier $@` | |
| 31 | + | ||
| 32 | + | This makes it possible to run it as e.g. *jverify.sh org.freepascal.rtl.System*. The reason for the large maximum heap size is because the verifier otherwise can run out of memory while verifying more complex classes. | |
| 33 | + | ||
| 34 | + | The verifier will report byte code offsets rather than source code line numbers when it detects an error. To obtain the corresponding source code line number, run *javap -l* on the same class. It will list the translation table from byte code offsets to source code line numbers for every function in that class. | |
| 35 | + | ||
| 36 | + | ## Java debuggers | |
| 37 | + | ||
| 38 | + | ### Source code searching logic | |
| 39 | + | ||
| 40 | + | All Java debuggers will look for source code in the same way as they look for classes. This means that if your class is in a package called *org.freepascal.rtl*, then the debugger will look for the source file containing that class in a directory structure *org/freepascal/rtl* that is located somewhere in the class or source directory path. | |
| 41 | + | ||
| 42 | + | I.e., if you specify */home/me/fpc/rtl/java* as a source directory, the debugger will look in */home/me/fpc/rtl/java/org/freepascal/rtl* for the sources of any class in the *org.freepascal.rtl* package rather than in the top level directory you specified. One way to deal with this is to create symbolic links to the source code next to the class files, if your operating system supports that, or to copy the source files next to the class files. | |
| 43 | + | ||
| 44 | + | ### jdb | |
| 45 | + | ||
| 46 | + | *jdb* is the standard command line debugger included with the JDK. It is very primitive and requires lots of typing, but other than that works fine. Some useful commands: | |
| 47 | + | ||
| 48 | + | - **Run debugger** (see the general note above for information about the *sourcebasedirectory* parameter, and make sure that you do not put the *.class* extension after the class name) | |
| 49 | + | - Unix: `jdb -classpath `*`/home/me/fpc/rtl/units/jvm-java:/some/other/directory`*` -sourcepath `*`sourcebasedirectory`*` `*`MainProgramClass`* | |
| 50 | + | - Windows: `jdb -classpath `*`D:\fpcjvm\units\rtl\jvm-java;C:\some\other\directory`*` -sourcepath `*`sourcebasedirectory`*` `*`MainProgramClass`* | |
| 51 | + | - **Start program and stop in main function** | |
| 52 | + | - `stop in `*`progname`*`.main` | |
| 53 | + | - `run` | |
| 54 | + | - **Continue execution** after it stopped at a breakpoint | |
| 55 | + | - `cont` | |
| 56 | + | - Go to the next source line, **stepping over calls** | |
| 57 | + | - `next` | |
| 58 | + | - Go to the next source line, **stepping into calls** (note: stepping into procedure variable calls or virtual class methods/constructors will not work, because they contain compiler generated code without debug information; set break points at the appropriate places to step into them) | |
| 59 | + | - `step` | |
| 60 | + | - **Repeat the last command** you typed | |
| 61 | + | - `!!` | |
| 62 | + | - **Set a breakpoint at the start of a particular function** | |
| 63 | + | - `stop in packagename.functionname` | |
| 64 | + | - e.g. `stop in org.freepascal.rtl.randomize` | |
| 65 | + | - **Set a breakpoint at a particular line** (note: "stop at" instead of "stop in", and specify a class name rather than a source file name) | |
| 66 | + | - `stop at packagename.class:linenumber` | |
| 67 | + | - e.g. `stop at TMyClass:123` or `stop at MyUnit:432` (in case the breakpoint is in a procedure/function that is not a method) | |
| 68 | + | - Show the **local variables and parameters** in the current stack frame | |
| 69 | + | - `locals` | |
| 70 | + | - **Print the value of an expression** (can include function calls) | |
| 71 | + | - `print variablename` (case-sensitive!) | |
| 72 | + | - `print variablename.field` (case-sensitive!) | |
| 73 | + | - **List the source code** around the current location in the code | |
| 74 | + | - `list` | |
| 75 | + | - See the current **backtrace** | |
| 76 | + | - `where` | |
| 77 | + | - `wherei` (includes byte code offsets) | |
| 78 | + | - Stop when an **exception is raised** (only works once the program has been started) | |
| 79 | + | - `catch all packagename.exceptionname` | |
| 80 | + | - e.g. `catch all java.lang.NullPointerException` | |
| 81 | + | - To catch all raised exceptions: `catch all java.lang.Throwable` (note that this will include a java.lang.ClassNotFoundException for every new class that gets loaded) | |
| 82 | + | - Get a complete **trace of all method calls and exits**, including the values they return (lots of output!) | |
| 83 | + | - `trace go methods` | |
| 84 | + | - When you are stopped at a break point, **go up/down one or more frames in the stack** (note that these are relative to where you are currently in the stack) | |
| 85 | + | - `up 1` | |
| 86 | + | - `down 2` | |
| 87 | + | - **Watchpoints** (reads and/or writes to a particular field -- note that these watchpoints are per class type, not per instance!) | |
| 88 | + | - `watch access package.classname.field` (-\> writes) | |
| 89 | + | - `watch all package.classname.field` (-\> reads + writes) | |
| 90 | + | - `unwatch all package.classname.field` (-\> remove watchpoint) | |
| 91 | + | - **Usage information** | |
| 92 | + | - `help` | |
| 93 | + | ||
| 94 | + | ### Eclipse | |
| 95 | + | ||
| 96 | + | It is undoubtedly possible to set up Eclipse so that it will debug FPC-generated Java class files. Anyone who figures out the details, feel free to describe them here. | |
| 97 | + | ||
| 98 | + | --- | |
| 99 | + | *From the Free Pascal wiki, page "FPC JVM/Debugging", as it stood on 2022-01-22 after a change by Jonas, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).* | |
| 100 | + | Category: JVM |
