diff --git a/java-jdi/pom.xml b/java-jdi/pom.xml
new file mode 100644
index 0000000000..3d70461dce
--- /dev/null
+++ b/java-jdi/pom.xml
@@ -0,0 +1,130 @@
+
+ 4.0.0
+ java-jdi
+ 0.1.0-SNAPSHOT
+ java-jdi
+ jar
+
+
+ com.baeldung
+ parent-java
+ 0.0.1-SNAPSHOT
+ ../parent-java
+
+
+
+
+ log4j
+ log4j
+ ${log4j.version}
+
+
+ org.slf4j
+ slf4j-api
+ ${org.slf4j.version}
+
+
+ ch.qos.logback
+ logback-classic
+ ${logback.version}
+
+
+ org.openjdk.jmh
+ jmh-core
+ ${jmh-core.version}
+
+
+ org.openjdk.jmh
+ jmh-generator-annprocess
+ ${jmh-generator.version}
+
+
+ org.apache.commons
+ commons-lang3
+ ${commons-lang3.version}
+
+
+ org.assertj
+ assertj-core
+ ${assertj.version}
+ test
+
+
+ com.sun
+ tools
+ ${tools.version}
+ system
+ ${java.home}/../lib/tools.jar
+
+
+
+
+ java-jdi
+
+
+ src/main/resources
+ true
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+ ${maven-javadoc-plugin.version}
+
+ 1.8
+ 1.8
+
+
+
+
+
+
+
+ integration
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+
+ integration-test
+
+ test
+
+
+
+ **/*IntegrationTest.java
+
+
+
+
+
+
+ json
+
+
+
+
+
+
+
+
+
+ 3.5
+
+ 3.6.1
+ 1.8
+ 1.7.21
+ 1.1.7
+ 1.8
+ 2.21.0
+ 3.0.0-M1
+ 3.0.2
+
+
diff --git a/java-jdi/src/main/java/com/baeldung/jdi/JDIExample.java b/java-jdi/src/main/java/com/baeldung/jdi/JDIExample.java
new file mode 100644
index 0000000000..f8f20553b8
--- /dev/null
+++ b/java-jdi/src/main/java/com/baeldung/jdi/JDIExample.java
@@ -0,0 +1,14 @@
+package com.baeldung.jdi;
+
+public class JDIExample {
+
+ public static void main(String[] args) {
+ String jpda = "Java Platform Debugger Architecture";
+ System.out.println("Hi Everyone, Welcome to " + jpda); //add a break point here
+
+ String jdi = "Java Debug Interface"; //add a break point here and also stepping in here
+ String text = "Today, we'll dive into " + jdi;
+ System.out.println(text);
+ }
+
+}
diff --git a/java-jdi/src/main/java/com/baeldung/jdi/JDIExampleDebugger.java b/java-jdi/src/main/java/com/baeldung/jdi/JDIExampleDebugger.java
new file mode 100644
index 0000000000..1d9de57ddb
--- /dev/null
+++ b/java-jdi/src/main/java/com/baeldung/jdi/JDIExampleDebugger.java
@@ -0,0 +1,171 @@
+package com.baeldung.jdi;
+
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.util.Map;
+
+import com.sun.jdi.AbsentInformationException;
+import com.sun.jdi.Bootstrap;
+import com.sun.jdi.ClassType;
+import com.sun.jdi.IncompatibleThreadStateException;
+import com.sun.jdi.LocalVariable;
+import com.sun.jdi.Location;
+import com.sun.jdi.StackFrame;
+import com.sun.jdi.VMDisconnectedException;
+import com.sun.jdi.Value;
+import com.sun.jdi.VirtualMachine;
+import com.sun.jdi.connect.Connector;
+import com.sun.jdi.connect.IllegalConnectorArgumentsException;
+import com.sun.jdi.connect.LaunchingConnector;
+import com.sun.jdi.connect.VMStartException;
+import com.sun.jdi.event.BreakpointEvent;
+import com.sun.jdi.event.ClassPrepareEvent;
+import com.sun.jdi.event.Event;
+import com.sun.jdi.event.EventSet;
+import com.sun.jdi.event.LocatableEvent;
+import com.sun.jdi.event.StepEvent;
+import com.sun.jdi.request.BreakpointRequest;
+import com.sun.jdi.request.ClassPrepareRequest;
+import com.sun.jdi.request.StepRequest;
+
+public class JDIExampleDebugger {
+
+ private Class debugClass;
+ private int[] breakPointLines;
+
+ public Class getDebugClass() {
+ return debugClass;
+ }
+
+ public void setDebugClass(Class debugClass) {
+ this.debugClass = debugClass;
+ }
+
+ public int[] getBreakPointLines() {
+ return breakPointLines;
+ }
+
+ public void setBreakPointLines(int[] breakPointLines) {
+ this.breakPointLines = breakPointLines;
+ }
+
+ /**
+ * Sets the debug class as the main argument in the connector and launches the VM
+ * @return VirtualMachine
+ * @throws IOException
+ * @throws IllegalConnectorArgumentsException
+ * @throws VMStartException
+ */
+ public VirtualMachine connectAndLaunchVM() throws IOException, IllegalConnectorArgumentsException, VMStartException {
+ LaunchingConnector launchingConnector = Bootstrap.virtualMachineManager().defaultConnector();
+ Map arguments = launchingConnector.defaultArguments();
+ arguments.get("main").setValue(debugClass.getName());
+ VirtualMachine vm = launchingConnector.launch(arguments);
+ return vm;
+ }
+
+ /**
+ * Creates a request to prepare the debug class, add filter as the debug class and enables it
+ * @param vm
+ */
+ public void enableClassPrepareRequest(VirtualMachine vm) {
+ ClassPrepareRequest classPrepareRequest = vm.eventRequestManager().createClassPrepareRequest();
+ classPrepareRequest.addClassFilter(debugClass.getName());
+ classPrepareRequest.enable();
+ }
+
+ /**
+ * Sets the break points at the line numbers mentioned in breakPointLines array
+ * @param vm
+ * @param event
+ * @throws AbsentInformationException
+ */
+ public void setBreakPoints(VirtualMachine vm, ClassPrepareEvent event) throws AbsentInformationException {
+ ClassType classType = (ClassType) event.referenceType();
+ for(int lineNumber: breakPointLines) {
+ Location location = classType.locationsOfLine(lineNumber).get(0);
+ BreakpointRequest bpReq = vm.eventRequestManager().createBreakpointRequest(location);
+ bpReq.enable();
+ }
+ }
+
+ /**
+ * Displays the visible variables
+ * @param event
+ * @throws IncompatibleThreadStateException
+ * @throws AbsentInformationException
+ */
+ public void displayVariables(LocatableEvent event) throws IncompatibleThreadStateException, AbsentInformationException {
+ StackFrame stackFrame = event.thread().frame(0);
+ if(stackFrame.location().toString().contains(debugClass.getName())) {
+ Map visibleVariables = stackFrame.getValues(stackFrame.visibleVariables());
+ System.out.println("Variables at " +stackFrame.location().toString() + " > ");
+ for (Map.Entry entry : visibleVariables.entrySet()) {
+ System.out.println(entry.getKey().name() + " = " + entry.getValue());
+ }
+ }
+ }
+
+ /**
+ * Enables step request for a break point
+ * @param vm
+ * @param event
+ */
+ public void enableStepRequest(VirtualMachine vm, BreakpointEvent event) {
+ //enable step request for last break point
+ if(event.location().toString().contains(debugClass.getName()+":"+breakPointLines[breakPointLines.length-1])) {
+ StepRequest stepRequest = vm.eventRequestManager().createStepRequest(event.thread(), StepRequest.STEP_LINE, StepRequest.STEP_OVER);
+ stepRequest.enable();
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+
+ JDIExampleDebugger debuggerInstance = new JDIExampleDebugger();
+ debuggerInstance.setDebugClass(JDIExample.class);
+ int[] breakPoints = {6, 9};
+ debuggerInstance.setBreakPointLines(breakPoints);
+ VirtualMachine vm = null;
+
+ try {
+ vm = debuggerInstance.connectAndLaunchVM();
+ debuggerInstance.enableClassPrepareRequest(vm);
+
+ EventSet eventSet = null;
+ while ((eventSet = vm.eventQueue().remove()) != null) {
+ for (Event event : eventSet) {
+ if (event instanceof ClassPrepareEvent) {
+ debuggerInstance.setBreakPoints(vm, (ClassPrepareEvent)event);
+ }
+
+ if (event instanceof BreakpointEvent) {
+ event.request().disable();
+ debuggerInstance.displayVariables((BreakpointEvent) event);
+ debuggerInstance.enableStepRequest(vm, (BreakpointEvent)event);
+ }
+
+ if (event instanceof StepEvent) {
+ debuggerInstance.displayVariables((StepEvent) event);
+ }
+ vm.resume();
+ }
+ }
+ } catch (VMDisconnectedException e) {
+ System.out.println("Virtual Machine is disconnected.");
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ finally {
+ InputStreamReader reader = new InputStreamReader(vm.process().getInputStream());
+ OutputStreamWriter writer = new OutputStreamWriter(System.out);
+ char[] buf = new char[512];
+
+ reader.read(buf);
+ writer.write(buf);
+ writer.flush();
+ }
+
+ }
+
+}
diff --git a/pom.xml b/pom.xml
index fc3567be51..58c5473744 100644
--- a/pom.xml
+++ b/pom.xml
@@ -457,6 +457,7 @@
java-collections-conversions
java-collections-maps
java-collections-maps-2
+ java-jdi
@@ -1156,6 +1157,7 @@
java-collections-conversions
java-collections-maps
java-collections-maps-2
+ java-jdi
java-ee-8-security-api
java-lite