Reproduced in: http://blog.csdn.net/jarfield/article/details/5250915
Recently, the main way to study Tomcat's work is to refer to the book "How Tomcat Works" and the source code of Tomcat 5.5.26.
The code structure of Tomcat is still quite clear, and the annotations are quite complete. However, after all, the code is static, it is difficult to thoroughly understand the collaboration between classes and classes, as well as the interaction of Run-time objects.
If the start of Tomcat, processing requests and stop the process of breakpoint debugging, see the whereabouts of Tomcat every step, then can solve the above problem.
So, another question came up: How to use Eclipse to remotely debug tomcat.
On the Internet to check some information, related articles or a lot of. I briefly combed through the solutions and principles, and was familiar with Tomcat's startup script.
How to debug a JVM remotely.
Remote debugging tomcat is essentially a remote debugging JVM. Rather than knowing the details of the JVM's own running, you need to understand the running details of the application on the JVM.
In any case, we have to get internal information about the JVM's runtime (such as viewing debugging information) and control the JVM's running process (such as stepping) to achieve the goal of debugging.
This is something that cannot be done by the debugger itself. Otherwise, the JVM's security is compromised. Unless the JVM provides some kind of backdoor, the debugger queries some run-time information and allows the debugger to send some control commands.
Had to sigh, the JVM was strong. From the beginning of J2SE 1.4.2, we have put forward and realized the JAVATM Platform Debugger architecture, referred to as JPDA.
JPDA Introduction
As the name suggests, JPDA defines a standard architecture for the debugger on the Java platform. The architecture consists of 3 main components: JVM TI, JDI, and jdwp.
The full name of the JVM ti is the Java Virtual Machine Tool Interface, which defines the functionality that the JVM must provide to support debugging and the corresponding access interface. These access interfaces are provided in the form of a native language and are implemented by the JVM, such as Sun's hotspot VM.
However, the JVM Ti is just a series of functions provided by the JVM, and how the debugger (especially the remote debugger) invokes it. In fact, the JVM TI's direct client is not a debugger, but a so-called "JPDA back-end" Dongdong. This dongdong should be part of the JVM, in the Sun JRE Bin directory can find Jdwp.dll (jdwp.so) library files, this is the JPDA back-end implementation. As I understand it, JPDA Back-end provides a variety of access modes (shared memory, sockets) that receive the debugger's request in these ways, and then invokes the JVM Ti interface.
The full name of JDI is the Java Debug Interface, which defines a high-level API to access the JVM's TI interface, provided in a pure Java language and implemented by the JDK (found in the Tools.jar of the Sun JDK). The debugger uses JDI directly to implement debugging functions. In contrast to Jpda Back-end, JDI's role is JPDA front-end.
The full name of JDWP is the Java Debug Wire Protocol, which defines the binary format for communication information between JPDA front-end and Jpda back-end. The communication information here consists of two types of request information that the debugger sends to the JVM and debugging information that the JVM sends to the debugger.
To summarize, the debugger invokes the JDI implementation provided by the JDK (JPDA front-end), via the JDWP protocol, and the JVM's own JPDA back-end (Jdwp.dll, jdwp.so, ...) for communication. JPDA Back-end learns debug information by invoking the JVM Ti interface, or sends control commands. JPDA Back-end then returns the debug information or command execution results to the debugger via the JDWP protocol.
How to enable JPDA
By default, the JVM does not enable JPDA back-end. The following parameters need to be loaded at the command line that starts the JVM:
-xdebug-xrunjdwp:transport=dt_socket, Address=8000,server=y,suspend=y
-xdebug
Enable debugging Features
-xrunjdwp
Enables the JDWP implementation, which contains several child options:
Transport=dt_socket
JPDA Front-End and Back-end transmission methods. Dt_socket means using socket transfer.
address=8000
The JVM listens for requests on port 8000.
Server=y
Y indicates that the JVM being started is being debugged. If n, indicates that the JVM being started is a debugger.
Suspend=y
Y indicates that the startup JVM pauses waiting until the debugger is connected.
Suspend=y this option is important. If you want to debug from the start of Tomcat, you must set up suspend=y.
Tomcat's startup script
As soon as Tomcat is started, JPDA is enabled and can be debugged. and Tomcat defaults to not enable JPDA, we need to manually open.
The method of opening JPDA is also very simple, do some modification to Tomcat's startup script, add the command line parameter that starts JPDA, it is OK.
However, the Tomcat startup script is still a bit complicated, not simply "Java ...". Let's start with a simple comb.
In the bin directory of the Tomcat 5.5.26 release, there are more than n scripts, where the scripts associated with Tomcat restart are (for example, Windows):
Startup.bat//Start Tomcat
Shutdown.bat/Stop Tomcat
Catalina.bat//contains core logic for start/stop Tomcat
Both Startup.bat and Shutdown.bat have the ability to start and stop by invoking Catalina.bat, so they have very little code. The main logic is in the Catalina.bat.
Catalina.bat is a powerful script that allows you to perform a variety of actions, including debug run start stop version, with parameters.
If we execute catalina.bat directly, we can see its usage instructions:
Startup.bat, is actually executes Catalina.bat start;shutdown.bat, actually is executes catalina.bat stop.
It is not difficult to guess, we can write a jdpa.bat, directly call Catalina.bat JPDA start, you should be able to enable JPDA. Let's make a copy of Startup.bat.
Call "%executable%" Start%cmd_line_args%
Modified into
Call "%executable%" JPDA start%cmd_line_args%
However,-xdebug-xrunjdwp:transport=dt_socket, address=8000,server=y,suspend=y, how these option parameters are passed to Catalina.bat.
Look at the comments in front of Catalina.bat, the value of the server is the default is Y,transport value is variable jpda_transport,address value is variable jpda_address,suspend value is variable Jpda_ SUSPEND. If it is not explicitly replicated, the value of these variables defaults to Dt_shmem jdbconn N (the default value indicates the use of shared memory as the transmission). These defaults are not what we need, and ECLISEP remote debugging currently supports only socket transmissions. Before calling Catalina.bat Jpda start, we set the appropriate values for these variables:
Set Jpda_transport=dt_socket
Set jpda_address=8000
Set Jpda_suspend=y
Call "%executable%" JPDA start%cmd_line_args%
Then, the direct execution of Jpda.bat,tomcat runs in JPDA-adjustable mode:
As you can see from the image above, Tomcat JPDA uses socket transmission, listening on port 8000. Tomcat startup is paused and only the debugger is connected to continue booting.
I put the full contents of the jpda.bat below, where the bold part is the code added on the Startup.bat basis:
@echo off
If "%os%" = = "Windows_NT" setlocal
REM---------------------------------------------------------------------------
rem JPDA script for the CATALINA Server
Rem
REM $Id: Jpda.bat 302918 2004-05-27 18:25:11z Yoavs $
REM---------------------------------------------------------------------------
REM Guess catalina_home if not defined
Set current_dir=%cd%
If not "%catalina_home%" = "" Goto gothome
Set catalina_home=%current_dir%
If exist "%catalina_home%/bin/catalina.bat" goto okhome
Cd..
Set catalina_home=%cd%
CD%current_dir%
: Gothome
If exist "%catalina_home%/bin/catalina.bat" goto okhome
echo the CATALINA_HOME environment variable is not defined correctly
echo this environment variable be needed to run this program
Goto END
: Okhome
Set Executable=%catalina_home%/bin/catalina.bat
REM Check that target executable exists
If exist "%executable%" goto okexec
Echo Cannot find%executable%
echo this file was needed to run this program
Goto END
: okexec
REM Get remaining unshifted command line arguments and save them in the
Set cmd_line_args=
: Setargs
If ""%1 "" = = "" "Goto Donesetargs
Set cmd_line_args=%cmd_line_args%%1
Shift
Goto Setargs
:d Onesetargs
Set Jpda_transport=dt_socket
Set jpda_address=8000
Set Jpda_suspend=y
Call "%executable%"JPDAStart%cmd_line_args%
: End
remote debugging tomcat in Eclipse
First, the source code for Tomcat 5.5.26 is divided into container connectors Jasper Servletapi build five projects, which are imported into eclipse. Start the related code primarily in container, and as it is the current project, open the Debug Configurations dialog box.
Then create a "Remote Java application", Connection type Select "Standard (Socket Attach)", and the host fills in localhost (the host address where Tomcat resides), Port fill in 8000. Finally click "Apply" to save.
First make sure that Jpda.bat,tomcat is waiting for the debugger to connect, and then perform the debug configuration,eclipse above to connect to Tomcat.
Tomcat starts with the main method of Bootstrap, I set a breakpoint in the first line of code, and Tomcat's startup stops in this line:
Then, let Tomcat continue, and we can see that the console is outputting the startup information.