Java Debugging Options
Running a Java program with the -Xdebug and -Xrunjdwp
options enables remote debugging capabilities. Here's a breakdown of the
command you provided:
bash
java -Xdebug
-Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y Test |
- -Xdebug:
This option is deprecated and no longer required in newer versions of Java
(since Java 5). The debug options are configured via the -Xrunjdwp
argument.
- -Xrunjdwp:
This argument configures the Java Debug Wire Protocol (JDWP).
- transport=dt_socket:
Specifies the transport mechanism (socket-based communication).
- address=8787:
Specifies the port number for the debugger to attach.
- server=y:
Indicates that the JVM should act as a debug server, waiting for a
debugger to attach.
- suspend=y:
Causes the JVM to pause execution until a debugger attaches. This is
useful for ensuring that you don't miss any early breakpoints.
This setup is useful for debugging applications running in
different environments, such as development, testing, or even production, with
caution.
Java Debugger (jdb)
Features:
- Command-Line
Interface:
- jdb is
a command-line tool that provides basic debugging capabilities.
- Breakpoint
Management:
- You
can set, clear, and list breakpoints in your code.
- Step
Execution:
- You
can step through code line by line, step into methods, and step out of
methods.
- Variable
Inspection:
- You
can inspect variables, evaluate expressions, and monitor changes in
variable values.
- Thread
Management:
- You
can list threads, inspect their states, and control their execution.
Basic Usage:
- Starting
jdb:
- Attach
jdb to a running JVM:
bash
jdb -attach
8787 |
- Setting
Breakpoints:
- Set
a breakpoint at the beginning of a method:
jdb
stop in
com.example.MyClass.myMethod |
- Running
and Controlling Execution:
- Continue
execution until the next breakpoint:
jdb
cont |
- Step
to the next line:
jdb
step |
- Inspecting
Variables:
- Print
the value of a variable:
jdb
print
myVariable |
- Thread
Management:
- List
all threads:
jdb
threads |
Drawbacks:
- Limited
Features:
- Compared
to modern IDEs, jdb lacks advanced debugging features such as visual
breakpoints, integrated variable inspection [Simple variable, Existing
static variable with-out changes, Existing method change business logic,
Existing static method change business logic, Existing inner class
changes business logic, Existing inner class business logic], and
memory analysis tools.
- Drawback:
which is integrated variable inspection not support [Existing static
variable with value changes, new method adds, New static method, add new
Enum, existing new enum change business value, add inner class, add new
class]
- Steep
Learning Curve:
- Command-line
debugging can be cumbersome and requires familiarity with jdb commands.
- Manual
Effort:
- Managing
breakpoints, stepping through code, and inspecting variables is more
labor-intensive without the convenience of a graphical interface.
- Usability:
- For
large-scale applications, debugging with jdb can be less efficient and
more error-prone.
Modern Alternatives
Modern Integrated Development Environments (IDEs) like
IntelliJ IDEA, Eclipse, and NetBeans offer robust debugging tools with
graphical interfaces that overcome the limitations of jdb:
- Breakpoints:
Set and manage breakpoints visually.
- Step
Execution: Step through code with buttons and keyboard shortcuts.
- Variable
Inspection: Hover over variables to inspect their values and see
evaluations.
- Thread
Management: Manage and inspect threads with an intuitive interface.
- Advanced
Features: Memory analysis, performance profiling, and other tools are
integrated into the IDE.
New tools how to run:
·
Create A Project give the example hotswaptool Add two jar file hotswaptool bcel-5.2.jar (this should be
download from google) tools.jar (this is coming
from your jdk path like D:\Software\java\jdk1.8.0_05\lib) ·
Copy the below code and add in your source
directory. ·
Run this program in java application ·
see the open window. ·
Now java hotswaptool is ready ·
Enabling the Debug Mode in your remote machine
project where you put the hot .class file ·
To run a regular serverless Java class Test
with debugging enabled in the Oracle HotSpot JVM, you need to use the
following command: java -Xdebug
-Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y Test ·
Start the server and call api. ·
If you need any business changes .class file
in remote machine without restart your server goto below step ·
Go to your local machine and change the
business logic and compile ·
Run the hot swap tool ·
Give the remote machine IP address ·
Give the remote machine debug port number like
8787 ·
Browse the .class file from your local ·
Click the hotswap ·
Done · Again
call api see the result it will effected |
Java
package
com.kartik.org; import
javax.swing.JFrame; /** * * @author kmandal * */ public class
SwapDemo { public static void main(String[] a) { Swap frame = new Swap(); frame.setTitle("Hot Swap Tool"); frame.setVisible(true); frame.setBounds(10, 10, 500, 500);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setResizable(false); frame.setLocationRelativeTo(null); } } |
Java
package
com.kartik.org; import
java.awt.Container; import
java.awt.event.ActionEvent; import
java.awt.event.ActionListener; import
java.awt.event.FocusEvent; import
java.awt.event.FocusListener; import
java.awt.event.KeyAdapter; import
java.awt.event.KeyEvent; import
java.awt.event.MouseAdapter; import
java.awt.event.MouseEvent; import
java.io.File; import
java.io.IOException; import
javax.swing.JButton; import
javax.swing.JFrame; import
javax.swing.JLabel; import
javax.swing.JOptionPane; import
javax.swing.JTextField; import
javax.swing.SwingUtilities; import
org.apache.bcel.classfile.ClassParser; import
org.apache.bcel.classfile.JavaClass; /** * * @author kmandal * */ public class
Swap extends JFrame implements ActionListener,Runnable { private static final long serialVersionUID =
1L; private String ipAddress; private String portNumber; private String absoulatePath; private String realPath; private File file; public String getIpAddress() { return ipAddress; } public void setIpAddress(String ipAddress) { this.ipAddress = ipAddress; } public String getPortNumber() { return portNumber; } public void setPortNumber(String portNumber)
{ this.portNumber = portNumber; } public String getAbsoulatePath() { return absoulatePath; } public void setAbsoulatePath(String
absoulatePath) { this.absoulatePath = absoulatePath; } public String getRealPath() { return realPath; } public void setRealPath(String realPath) { this.realPath = realPath; } public File getFile() { return file; } public void setFile(File file) { this.file = file; } Container container=getContentPane(); //JPanel panel = new JPanel(new
GridLayout(0, 1)); JButton headerLabel=new JButton("Swap
Tool "); JLabel ipLabel=new JLabel("Ip
Address: *"); JLabel portNoLabel=new JLabel("Port
number: *"); JLabel fileChooseLabel=new
JLabel("Choose File: *"); JTextField ipTextField=new JTextField(); JTextField portTextField=new
JTextField(); JTextField fileName = new JTextField(); JButton browse = new
JButton("Browse"); JButton loginButton=new
JButton("Swap File"); JButton resetButton=new
JButton("Re-set"); Swap() { //Calling methods inside constructor. setLayoutManager(); setLocationAndSize(); addComponentsToContainer(); } public void setLayoutManager() { container.setLayout(null); } public void setLocationAndSize() { headerLabel.setBounds(50,100,430,30); headerLabel.setOpaque(true); // headerLabel.setBackground(Color.GREEN); //Setting location and Size of each
components using setBounds() method. ipLabel.setBounds(50,150,100,20); portNoLabel.setBounds(50,200,100,20);
fileChooseLabel.setBounds(50,250,100,20); ipTextField.setBounds(150,150,200,20);
portTextField.setBounds(150,200,100,20); fileName.setEditable(false); fileName.setBounds(150,250,220,20); browse.setBounds(380,250,100,20); loginButton.setBounds(50,300,100,25); resetButton.setBounds(200,300,100,25); } public void addComponentsToContainer() { container.add(headerLabel); //Adding each components to the
Container container.add(ipLabel); container.add(portNoLabel); container.add(fileChooseLabel); ipTextField.addFocusListener(new
FocusListener() { public void focusLost(FocusEvent fe) { setIpAddress(ipTextField.getText()); } public void focusGained(FocusEvent fe) { } }); ipTextField.addKeyListener(new
KeyAdapter() { public void keyTyped(KeyEvent e) { if (ipTextField.getText().length() >=
50) e.consume(); } }); container.add(ipTextField); portTextField.addFocusListener(new
FocusListener() { public void focusLost(FocusEvent fe) { setPortNumber(portTextField.getText()); } public void focusGained(FocusEvent fe) { } }); portTextField.addKeyListener(new
KeyAdapter() { public void keyTyped(KeyEvent e) { char letter = e.getKeyChar(); if (portTextField.getText().length()
>= 15) { e.consume(); } else if (!Character.isDigit(letter)) { e.consume(); } } }); container.add(portTextField); container.add(fileName); browse.addMouseListener(new
MouseAdapter() { public void mouseClicked(MouseEvent evt) { if
(SwingUtilities.isLeftMouseButton(evt)) { Chooser frame = new Chooser(); fileName.setText(frame.fileName); setRealPath(frame.fileName); setFile(frame.file); } } }); container.add(browse); loginButton.addMouseListener(new
MouseAdapter() { public void mouseClicked(MouseEvent evt) { if
(SwingUtilities.isLeftMouseButton(evt)) { boolean flag=validation(); if(flag){ /*Thread swapThread = new Thread(); swapThread.start(); try { System.out.println("Start
the First Sleep"); Thread.sleep(5000); System.out.println("Start
the hot swap");*/ hotSwap(); /*System.out.println("Start
the Second Sleep"); Thread.sleep(5000); System.out.println("End
the sleep"); } catch (InterruptedException e)
{ e.printStackTrace(); }*/ } } } }); container.add(loginButton); container.add(resetButton); } /** * * @param fullStr * @return */ private void hotSwap() { StringBuffer br = new StringBuffer(); generateComand(br); String command = br.toString(); System.out.println(command); StringBuffer br2 = new StringBuffer(); String packageName = null; File f = getFile(); String aa = f.getName(); String[] arrOfStr =
aa.split("\\.", -1); String filePath =
filePathMethod(getRealPath()); if (f.exists()) { ClassParser classParser = null; try { classParser = new ClassParser(filePath); } catch (IOException e) { e.printStackTrace(); } JavaClass javaClass = null; try { javaClass = classParser.parse(); } catch (IOException ioe) { System.out.println(filePath); } packageName = javaClass.getPackageName(); writeMethodInCommand(br2, packageName,
arrOfStr, filePath); HotSwap h = new HotSwap(); boolean isRunning =
h.isProcessRunning(command, br2.toString()); String processName = "java.exe"; if (isRunning) { h.killProcess(processName); } else { System.out.println("Not able to find
the process : " + processName); } } else { System.out.println("\nFile Path not
exist "); } } /** * This is find out the absoluteFilePath of
a file for any server * * @param fileName *
fileName * @param pathName *
pathName * @return absoluteFilePath */ public String filePathMethod(String
pathName) { String absoluteFilePath = ""; // String workingDir =
System.getProperty("user.dir"); String runnigServerOs =
System.getProperty("os.name").toLowerCase(); if (runnigServerOs.indexOf("win")
>= 0) { // if windows absoluteFilePath =
pathName.replaceAll("\\\\", "\\\\\\\\"); } else if
(runnigServerOs.indexOf("nix") >= 0 ||
runnigServerOs.indexOf("nux") >= 0 ||
runnigServerOs.indexOf("mac") >= 0) { // if unix or mac // absoluteFilePath = workingDir +
"/" + fileName; absoluteFilePath = pathName; } else { // unknow os? // absoluteFilePath = workingDir +
"/" + fileName; absoluteFilePath = pathName; } System.out.println("Final filepath :
" + absoluteFilePath); return absoluteFilePath; } /** * * @param br */ private void generateComand(StringBuffer br)
{ br.append("jdb -connect
com.sun.jdi.SocketAttach:hostname="); br.append(getIpAddress()); br.append(",port="); br.append(getPortNumber()); } /** * * @param br2 * @param packageName * @param arrOfStr * @param filePath */ private void
writeMethodInCommand(StringBuffer br2, String packageName, String[] arrOfStr,
String filePath) { br2.append("redefine"); br2.append(" "); br2.append(packageName); br2.append("."); br2.append(arrOfStr[0]); br2.append(" "); br2.append(filePath); } @Override public void actionPerformed(ActionEvent
e) { } public boolean validation() { if(getIpAddress().equals("")) { String message = "Please enter ip
address properly\n";
JOptionPane.showMessageDialog(container, message, "Dialog", JOptionPane.ERROR_MESSAGE); return false; } else
if(getPortNumber().equals("")) { String message = "Please enter
port number\n";
JOptionPane.showMessageDialog(container, message, "Dialog", JOptionPane.ERROR_MESSAGE); return false; } else
if(Integer.parseInt(getPortNumber())<=0) { String message = "Please enter
port number\n";
JOptionPane.showMessageDialog(container, message, "Dialog", JOptionPane.ERROR_MESSAGE); return false; } else if(getFile().equals("")) { String message = "Please enter
file which you need to swap \n";
JOptionPane.showMessageDialog(container, message, "Dialog", JOptionPane.ERROR_MESSAGE); return false; } return true; } @Override public void run() { // TODO Auto-generated method stub } } |
Java
package
com.kartik.org; import
java.io.BufferedOutputStream; import
java.io.BufferedReader; import
java.io.IOException; import
java.io.InputStreamReader; import
java.io.OutputStreamWriter; import
java.io.PrintWriter; public class
HotSwap { public boolean isProcessRunning(String
command,String write) { boolean flag=false; try { /* String array to execute commands
*/ String[] commands = new String[3]; commands[0] = "cmd"; commands[1] = "/c"; /* Command you want to execute */ // command[2] = "jdb -connect
com.sun.jdi.SocketAttach:hostname=192.168.211.180,port=8999"; //commands[2] = "jdb -connect
com.sun.jdi.SocketAttach:hostname=192.168.57.66,port=8999"; commands[2] = command; /* Create process */ Process p =
Runtime.getRuntime().exec(commands); /* Get OuputStream */ PrintWriter writer = new
PrintWriter(new OutputStreamWriter(new
BufferedOutputStream(p.getOutputStream())), true); /* Read the output of command prompt
*/ BufferedReader reader = new
BufferedReader(new InputStreamReader(p.getInputStream())); String line = reader.readLine(); /* Read upto end of execution */ int count=0; while (line != null) { /* Pass the value to command
prompt/user input */ // writer.println("redefine
com.journaldev.spring.PersonController
D:\\Kartik\\Karthik\\Spring-Boot-REST\\target\\classes\\com\\journaldev\\spring\\PersonController.class"); writer.println(write); System.out.println(line); if(count>=2){ return true; }else{ line = reader.readLine(); } count=count+1; } /* The stream obtains data from the
standard output stream of the process represented by this Process object. */ BufferedReader stdInput = new
BufferedReader(new InputStreamReader(p.getInputStream())); /* The stream obtains data from the
error output stream of the process represented by this Process object. */ BufferedReader stdError = new
BufferedReader(new InputStreamReader(p.getErrorStream())); String Input; while ((Input = stdInput.readLine())
!= null) { System.out.println(Input); } String Error; while ((Error = stdError.readLine())
!= null) { System.out.println(Error); } } catch (Exception e) { e.printStackTrace(); } return flag; } private static final String KILL =
"TASKKILL /F /IM "; public void killProcess(String serviceName)
{ try { Runtime.getRuntime().exec(KILL +
serviceName); System.out.println(serviceName+"
killed successfully!"); System.exit(0); } catch (IOException e) { e.printStackTrace(); } } } |
Java
package
com.kartik.org; import
java.io.File; import
javax.swing.JFileChooser; import
javax.swing.JFrame; /** * * @author kmandal * */ public class
Chooser extends JFrame { private static final long serialVersionUID =
1L; public JFileChooser chooser; public String fileName; public File file; public Chooser() { chooser = new JFileChooser(); int r = chooser.showOpenDialog(new
JFrame()); if (r == JFileChooser.APPROVE_OPTION) { fileName =
chooser.getSelectedFile().getPath(); file = chooser.getSelectedFile(); } } } |
Conclusion
While jdb provides essential debugging capabilities, its
command-line interface and limited features can make it less efficient for
complex debugging tasks compared to modern IDEs. However, it remains a useful
tool for remote debugging and scenarios where an IDE is not available.
Hot Swap tool |
0 Comments