Vincent Jia 博客

to be a better man, to be a bad man.

  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  29 随笔 :: 3 文章 :: 0 评论 :: 0 Trackbacks
Home  |  Java  |  Photography  |  Motorcycles  |  Eclipse  |  JRoller 星期四 2005年12月29日

Remote Debugging with Eclipse

How many times trying to fix a server-side Java problem appeared trivial, but getting to the source of the problem took all the time? A debugger attached to a remote Java application can shorten the defect-discovery times significantly and make the process more enjoyable.

The Java Debugger

The Java Debugger (jdb) is a dynamic, controlled, assignment-based debugging tool. It helps find and fix bugs in the Java language programs both locally and on the server. To use jdb in a J2EE application server you must first launch it with debugging enabled and attach to the server from the debugger through a JPDA port (Default port is 1044).

The default JPDA options for J2EE servers are as follows:

-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=1044

The jdb parameters specify the way debugger will operate. For instance transport=dt_socket instructs the JVM that the debugger connections will be made through a socket while the address=1044 parameter informs it that the port number will be 1044. Similarly, if you substitute suspend=y, the JVM starts in suspended mode and stays suspended until a debugger is attached to it. This may be helpful if you want to start debugging as soon as the JVM starts.

Here is a table with descriptions of the jdb parameters:

Debugger Launch Parameters

Launch Parameter

Description

-Xdebug

Enables the application to be debugged.

-Xnoagent

Disables the sun.tools.debug agent so that the JPDA debugger can properly attach its own agent.

-Djava.compiler=NONE

Disables the JIT (Just-In-Time) compiler.

-Xrunjdwp

Loads the reference implementation of the Java Debug Wire Protocol, which enables remote debugging.

transport

Name of the transport to be used when debugging the application. The value can be dt_shmem (for a shared memory connection) or dt_socket (for a socket connection). Shared memory connections are available only on Windows machines.

server

If this value equals n, the application attempts to attach to the debugger at the address specified in the address subparameter. If this value equals y, the application listens for a connection at this address.

address

For socket connections, specifies a port number used for communi-cation between the debugger and the application.

For shared memory connections, specifies a name that refers to the shared memory to be used. This name can consist of any combination of characters that are valid in filenames on a Windows machine except the backslash. You use this name in the Name field of the Attach dialog box when you attach the debugger to the running application.

suspend

If the value is n, the application starts immediately. If the value is y, the application waits until a debugger has attached to it before executing.


Debugging WebLogic

Debugging WebLogic is no different than debugging any other Java remote application. You need to make sure to launch it with the required debugging arguments and attach a debugger. In the case of WebLogic 8.1, you need to add these arguments to the startup script. WebLogic comes with several launch scripts (*.sh and *.cmd) under BEA_HOME/weblogic81/server/bin.

  1. Locate startWSL.cmd and add the following variable DEBUG_OPTS:
    set DEBUG_OPTS = -Xdebug -Xrunjdwp:transport= dt_socket,address=1044,server=y,suspend=n
  2. Next, insert the new variable to the WebLogic startup command, after "%JAVA_HOME%\bin\java" and preferably before the other options.
  3. Your startup script should look like:

    "%JAVA_HOME%\bin\java" %DEBUG_OPTS% %JAVA_VM% %MEM_ARGS% %JAVA_OPTIONS%-Dweblogic.Name=%SERVER_NAME% -Dweblogic.management.username= %WLS_USER%-Dweblogic.management.password= %WLS_PW% -Dweblogic.management.server= %ADMIN_URL%-Dweblogic.ProductionModeEnabled= %PRODUCTION_MODE%-Djava.security.policy= "%WL_HOME%\server\lib\weblogic.policy" weblogic.Server


Debugging IBM WebSphere 5.x/6.x

(Thanks to Michael Murphy)

  1. Open WebSphere 5.X/6.X Console
  2. Navigate to Servers | Application Servers | [SERVERNAME] | Process Definition | Java Virtual Machine
  3. Check off Debug Mode
  4. Arguments can be edited in the field called Debug arguments. You can paste this line and use the same port 1044 to debug from Eclipse:
    -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=1044

Debugging JBoss

Same as WebLogic, except that you need to change run.bat/run.sh located under JBOSS_HOME/bin.

Linux users should see something similar to this:

 $ cd /var/jboss4/bin
$ sh ./run.sh
=========================================================================

JBoss Bootstrap Environment

JBOSS_HOME: /var/jboss4

JAVA: /usr/java/j2sdk1.4.2_06/bin/java

JAVA_OPTS: -server -Xms128m -Xmx128m -Dprogram.name=run.sh

DEBUG_OPTS = -Xdebug -Xrunjdwp:transport= dt_socket,address=1044,server=y,suspend=n

CLASSPATH: /var/jboss4/bin/run.jar:/usr/java/j2sdk1.4.2_06/lib/tools.jar

=========================================================================

Hot Swapping Code in JBoss

Let's assume your JBoss is rooted in C:\JBoss and the application classpath is C:\classes\myapp. You can tell Eclipse to compile your application classes to this folder by setting it as the project output folder. This should generally work, but there is a small catch.

If you are like me and use Ant scripts to build-clean from time to time you may want to ensure that the contents of the output folder are not accidentally cleaned by Eclipse. Since Eclipse has a Clean function for projects it is easy to swipe the entire folder and get only the class files. So, to keep the Ant-generated files alongside with the *.class files that Eclipse will generate you must tell Eclipse to be a little less harsh to your output folder.

  1. Begin by setting your Java project's output folder. Assuming JBoss' application classpath is outside your Eclipse workspace, it may be a good idea to create a linked folder.
  2. Navigate to File | New | Folder.
  3. Enter classes as folder name. Click Advanced and point the new folder to C:\classes\myapp.
    Click to enlarge...
  4. In the Project Properties page page, change the output folder to the newly created classes folder. Click Project | Properties | Java Build Path. Fill the Default output foder with the following:
    Click to enlarge...
  5. You are almost there. Navigate to Window | Preferences... | General | Workspace and check Build automatically.
    Click to enlarge...
  6. Lastly, tell Eclipse not to erase other files in the output folder every time it builds the project. While still in Preferences navigate to Java | Compiler | Building and uncheckScrub output folders when cleaning projects. That's it. Now every time you save a Java file, Eclipse will recompile it and JBoss will reload it.
    Click to enlarge...

Debugging Tomcat

Debugging Tomcat is very much similar to WebLogic and JBoss, except that you need to change catalina.bat/catalina.sh located under TOMCAT_HOME/bin.

Tomcat is a special case in the sense that there are couple of strategies you can employ to dubug and achieve hot code replacement.

Using Sysdeo Tomcat Plugin for Eclipse

Sysdeo are the creators of a small and powerful Tomcat plugin for Eclipse. Among other things using Sysdeo will allow you to debug Tomcat and reload contexts.

  1. Begin by downloading the plugin from Sysdeo's website.
  2. Unzip the archive to ECLIPSE_HOME/plugins folder.
  3. Launch Eclipse. Navigate to Window | Preferences... | Tomcat.
  4. In the Plugin Preferences page, specify Tomcat version and home. There are two ways to declare contexts in Tomcat. The new way is to create context files under TOMCAT_HOME/conf/Localhost. In Preferences | Tomcat | Context declaration mode select Context files and the contexts folder should be automatically selected (Tomcat 5.5.12).
    Click to enlarge...
  5. Close Preferences. Open any perspective. You should see three cat buttons on the toolbar. To launch Tomcat, click the first icon. This will create a new server process and the Eclipse debugger will be attached automatically. The debug mode is a preference which can be modified from the Preferences page.
  6. You can also add projects to Tomcat's source and classpath lookup path, which you'll need if you plan to step through the code. One thing you'll notice is that the plugin will redirect Tomcat's output to Eclipse's console. Another important thing is the ability to append or prepend JARs to the classpath or just pass JVM arguments to the launcher. You can set all these in the plugin preferences page.

Configuring Reloadable Tomcat Context

Let's say that for whatever reason you do not want to use Sysdeo. You can still debug Tomcat easily:

  1. First create a new Tomcat context for your application. Navigate to TOMCAT_HOME\conf\Catalina\localhost and create a new file, say, myapp.xml. This will become part of your url, so to access your app you'll have to type http://localhost:8080/myapp.
  2. Enter the following in myapp.xml:
    <Context docBase="c:/eclipse_workspace/myapp/WebRoot" path="/HelloWorld"/>
    This assumes you have a web application containing WEB-INF in c:/eclipse_workspace/myapp/WebRoot
  3. Create two environment variables:
    C:\>set JDPA_ADDRESS=1044
    C:\>set JDPA_TRANSPORT=dt_socket
  4. Now, you can launch Tomcat with these debug options:
    C:\Tomcat-5.5.12\bin\>catalina jdpa start
  5. Use Eclipse to connect to Tomcat through port 1044


Hot Swap Code and Automatic Context Reloading with Tomcat

Debugging will in some cases involve changing the class and you'll naturally want the debugger to pick the latest changes and reload them seamlessly. Well, that's normally the case, but not always. To guarantee reloading of the context, you can define the context as reloadable.
Open myapp.xml and change it to:

<Context docBase="c:/eclipse_workspace/myapp/WebRoot" path="/HelloWorld" reloadable="true"/>

Now the context should relaod every time you make a change to any Java file. Note that it may take a few moments to load, especially if the application is large. Similarly, if you have heavy bootstrap servlet you may want to disable automatic reload because even the smallest change will cause the entire context to reload.


Debugging JSP Pages

Debugging JSP in Eclipse can be done in several ways. The easy way is to get one of several commercial plugins available with built-in support for JSP debugging. One such plugin is MyEclipse and another is NitroX. In addition to JSP debugging these commercial plugins come with tons of other features such as Database Explorer, XML editing, UML and ERD diagrams and more. One side effect of this feature bonanza though is that the environment becomes "fatter" and less responsive. In my experience, both plugins caused Eclipse to slow down considerably and at times the environment became very unstable. Similarly, these memory-hungry plugins were the cause of frequent Out of Memory Exceptions and subsequent environment crashes. Long story short, I finally bit the bullet I decided to return to the basics. That's when I realized that debugging JSPs can be achieved without any plugins. The process is a little more time consuming to set up, but the reward is a fast and stable environment.

Debugging JSPs becomes easier after knowing that they are converted into Java files. This takes place at runtime, just before they are compiled by javac. In this example I am going to set JBoss, however you can use a similar technique to set other servers. Since JBoss uses jasper and javac for Java generation and compilation, it makes sense to begin by creating a Java project with the source folder pointing to JBoss' JSP output folder. This project will be a regular java project with one notable difference: the size of its source folder will change quite frequently as a result of changes made to the JSPs and runtime recompilation done by JBoss.

Follow the following steps to set Eclipse for JSP debugging:

  1. Begin by launching JBoss.
  2. Locate where JBoss places compiled JSPs. Depending on whether you deploy WARs and your actual server configuration you should find it somewhere similar to:

    JBOSS_HOME\server\j2ee\work\jboss.web\localhost\myapp
  3. Launch Eclipse. Navigate to File | New | Other.... Select Java Project and click Next.
  4. In the New Java Project page, enter a Project name, for instance my_jsp. Leave everything in default state and click Finish.
    Click to enlarge...
  5. Create a new linked folder to JBOSS_HOME\server\j2ee\work\jboss.web\localhost\myapp. This folder will later become the project's source folder.
    Click to enlarge...
  6. Make src a source folder. Navigate to File | New | Source Folder
  7. Click Browse and select src. Click Finish. Agree with the dialog that follows.
    Click to enlarge...
  8. While you are in the same dialog, change the Project output folder to src.
  9. Eclipse will try to compile my_jsp, but you'll see many problems. Two major issues have to be resolved in order for the project to compile properly. First, the the jasper libraries have to be added to the project's classpath and second it has to refer to your Java code project my_java_code(Assuming you have a separate Java project hosting domain classes and servlets).
  10. Open Project properties and add the following libraries to the classpath:
    • JBOSS_HOME/server/j2ee/deploy/jbossweb-tomcat50.sar/jasper-runtime.jar
    • JBOSS_HOME/server/j2ee/lib/javax.servlet.jsp.jar

    Also, click the Projects tab and my_java_code to the classpath. Now the my_jsp projects classpath should look like:
    <?xml version="1.0" encoding="UTF-8"?>
    <classpath>
    <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
    <classpathentry excluding="src/" kind="src" path=""/>
    <classpathentry kind="src" path="src"/>
    <classpathentry kind="lib" path="C:/jboss-4.0.1sp1/server/j2ee/deploy/jbossweb-tomcat50.sar/jasper-runtime.jar"/>
    <classpathentry kind="lib" path="C:/jboss-4.0.1sp1/server/j2ee/lib/javax.servlet.jsp.jar"/>
    <classpathentry combineaccessrules="false" kind="src" path="/my_java_code"/>
    <classpathentry kind="output" path="src"/>
    </classpath>
  11. Navigate to Project | Build Project. This time it should build with no probelms.
  12. Start JBoss. Use Eclipse debugger to begin a debug session.
  13. Open a browser and access several pages. Go back to Eclipse, right-click on my_jsp and select Refresh. You should now have new Java classes that did not exist before.
  14. Double-click on any new Java class. Open the _jspService method and set a breakpoint. Go back to the browser and hit Refresh.
  15. The JSP page should come up and you should be able to step through the code. The interesting thing is that while the debugger will be stepping through the Java class representing the JSP page the JSP editor will automatically link the tow and you'll get the impression you're stepping through the JSP code itself. All variables will be set and after that you can really debug the page as any other Java class. Now you should be all set!

Debugger Verification

Now you can launch your application in debug mode. Just to make sure that the server is listening to port 1044 you can run netstat /a. You should see port 1044 in the list of open ports (See Figure 1: List of open ports: netstat -a).

Figure 1 List of open ports: netstat -a


The Eclipse Connection

After making sure WebLogic is listening for incoming connections on port 1044, what is left is to tell Eclipse to connect to this port and you are ready to debug.

  1. In Eclipse, navigate to Run | Debug(See Figure 2: Create new Remote Java Application configuration in Eclipse).
  2. Select Remote Java Application, on the left column. Click New, on the bottom of the same column.
  3. In the Create configuration screen you'll be prompted to enter some values. Start with a meaningful name. In my case that's WebLogic Instance. For Project, select the Java project that contains the source code you want to debug. Leave Connection Type in default, i.e. Standard (Socket Attach). For Host, enter localhost. If you want to debug a remote server, enter its hostname or IP address. For port, enter 1044 or the port you defined in your WebLogic startup script.
  4. Click Apply
  5. Make sure WebLogic instance is running in debug mode. In the same screen click Debug. Eclipse should automatically take you to the Debug perspective and you should see a stack trace in the Debug view.
  6. If you are not automatically taken to the Debug perspective, select Window | Open Perspective | Other and then click Debug.

Figure 2 Create new Remote Java Application configuration in Eclipse


Figure 3 Breakpoint hit in Eclipse debugger

Eclipse Debug window should automatically pop-up with the stack pointer on your first breakpoint (See Figure 3: Breakpoint hit in Eclipse's debugger). After that, you can use all the various functions that the debugger has to offer, namely variable assignments, step-into, drop to frame, etc.


References


System Information

  • Windows XP Professional
  • JDK 1.4.2_07
  • Eclipse 3.2
  • BEA WebLogic 8.1
  • JBoss 4.0.2
  • Tomcat 5.5.12

About the Author

Levent Gurses is a Washington, DC-based technology consultant. He is also one of the co-founders of Jacoozi, an integrated solutions provider based in Alexandria, VA. In his professional life Levent helps clients overcome their J2EE challenges and develop leaner and meaner software development practices. Most of his free time goes in reading and motorcycle racing.


( 2005年12月29日, 05:35:52 下午 EST )Permalink留言 [23]Print
posted on 2010-08-09 09:52 iLinux 阅读(491) 评论(0)  编辑  收藏

只有注册用户登录后才能发表评论。


网站导航: