DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

The software you build is only as secure as the code that powers it. Learn how malicious code creeps into your software supply chain.

Apache Cassandra combines the benefits of major NoSQL databases to support data management needs not covered by traditional RDBMS vendors.

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Related

  • Ulyp: Recording Java Execution Flow for Faster Debugging
  • Error Handling Inside Kumologica Subflow
  • Techniques You Should Know as a Kafka Streams Developer
  • MuleSoft Parallel ForEach Processor vs. ForEach Processor

Trending

  • Orchestrating Microservices with Dapr: A Unified Approach
  • A Simple, Convenience Package for the Azure Cosmos DB Go SDK
  • Secrets Sprawl and AI: Why Your Non-Human Identities Need Attention Before You Deploy That LLM
  • Manual Sharding in PostgreSQL: A Step-by-Step Implementation Guide
  1. DZone
  2. Testing, Deployment, and Maintenance
  3. Maintenance
  4. Debugging Program Control Flow

Debugging Program Control Flow

Control flow is much more than step over. You can "jump" to arbitrary code offsets while debugging to reproduce elaborate states and behaviors!

By 
Shai Almog user avatar
Shai Almog
DZone Core CORE ·
Dec. 16, 22 · Tutorial
Likes (2)
Comment
Save
Tweet
Share
3.7K Views

Join the DZone community and get the full member experience.

Join For Free

As of now, I have published the first three videos of the course and will publish the fourth tomorrow. I plan to publish two videos per week on YouTube to maximize the impact but here, I'll only blog one lesson per week to avoid oversaturation. I shot about four hours of video content and still haven’t finished the 2nd module out of eight. This course will be very detailed and intensive.

I’m working on the course platform right now, making good progress, and hope to publish it soon enough here. It might already be live by the time you read this!

It’s important to me that the user experience for the course platform is satisfying. So I avoided DRM as much as possible. Hopefully, people will respect that and the effort I’m putting into this. I’m building the course platform on Spring Boot 3 with GraalVM, so it will ideally be lean, fast, and pretty simple. I plan to host the videos on YouTube as unlisted videos to give a decent viewing experience. This means developers could betray my trust and share unlisted videos. I hope they don’t.

My reasoning here is low overhead and excellent performance. I would also like to make the course free in a few years. By using YouTube, I can make the course free by making the videos public.

The following video discusses control flow in debugging. This starts with the basics but can get pretty deep for jump-to-line, force return, etc. These are tools that can significantly change the way we debug code.

Don't forget to check out my book and subscribe to the YouTube channel for future videos!


Transcript

Welcome back to the second part of debugging at Scale, where you can learn the secret tricks of debugging.

In this section, we’ll discuss the most basic aspect of debugging. We hit a breakpoint. Now what?

Well, this is where debuggers let us control the flow to investigate how everything works in a controlled environment.

So what’s on the agenda for today?

We’ll discuss stepping over and into code; I hope most of this list is familiar to you. The last two items where we disrupt the control flow might not be familiar to you. I’m pretty sure most of you aren’t familiar with the last item on the agenda. How do I know? Stay tuned and find out!

Step Over, Into, Out, and Force

Step over is the most basic form of control flow. We let the code in the line execute, and then we can inspect the results in the variable pane. It’s simple and easy.

In this case, I just pressed the button here a couple of times, but I could also just press F8 to get the same effect…

Next, we’ll discuss two distinct operations, step into and the related step out. Step into goes into the method we invoke. Notice that if there’s no method to go into, the step into will act like step over.

We have two step-into operations. The regular one and the force-step into, which normally acts the same way. We need the force version when we want to step into an API that IntelliJ will normally skip. We can press F7 to step into a method. We can press Shift F7 to force step into.

When we finished looking at a method and don’t care about the rest, we can step out. This executes the rest of the method and returns. Notice that if we have a breakpoint before the return, it would still stop at the breakpoint, as we see in this case. We can press this button here to step out, or we can press shift-F8 to do the same thing.

Continue and Run To Cursor

Continue proceeds with the execution of the project until the breakpoint is hit again. This is also called resume. It’s a simple feature that we use a lot. You can continue by pressing the special version of the play button here. The shortcut is also helpful since we use it a lot; it’s F9.

Run to cursor lets us skip lines that are uninteresting and reach the code that matters. We can set a breakpoint at that line to get the same effect, but this is sometimes more convenient as it removes the need to set and unset a breakpoint. We can press this button to run to the cursor, or we can use ALT-F9 as the shortcut for this feature.

Force Return and Throw Exception

This feature is known as force return in IntelliJ/IDEA.

To see the force return option, we right-click on the stack trace and can see a set of options. An even more interesting option is drop frame which I’ll show soon. Notice the throw exception option, which is identical to force return, but it throws an exception from the method. Once I click this option.

I’m shown a dialog to enter the return value from the method. This lets me change the value returned from the method, which is very useful when I want to debug a hard-to-reproduce bug. Imagine a case where a failure happens to a customer, but you can’t reproduce it. In this case, I can simulate what the customer might be experiencing by returning a different value from the method.

Here the value is a boolean variable, so it’s simple. But your code might return an object; using this technique, you can replace that object with an arbitrary value. A good example would be null; what if this method returned null? Would it reproduce the problem my user is experiencing?

Similarly, throw exception lets us reproduce edge cases, such as throwing an exception due to an arbitrary failure.

Once we press OK, we return with a different value. In this case, I was at the edge of the method, but I could have done it at the start of the method and skipped the execution of the method entirely. This lets us simulate cases where a method might fail, but we want to mock its behavior. That can make sense if we can’t reproduce the behavior seen by the customer. We can simulate by using tools like this.

Drop Frame

Drop frame is almost as revolutionary, but it’s also more of a “neat trick.” Here I stepped into a method by mistake. Oops, I didn’t want to do that. I wanted to change something before stepping in… Luckily, there’s a drop frame. We saw I can reach it in the right-click menu; you can also click here to trigger it.

Drop frame effectively drops the stack frame. It’s an undo operation. But it isn’t exactly that. It can’t undo the state changes that occurred within the method we stepped into. So if you stepped into the method and variables that aren’t on the stack were changed, they would remain changed.

Variables on the stack are those variables that the method declares or accepts as arguments; those will be reset. However, if one of those variables points at an object, then that object resides in the heap, and changes there can’t be reset by unwinding the stack.

This is still a very useful feature similar to force return, with the exception that it will return to the current line, not the next line. So it won’t return a value.

This gets even better than that!

Jump to Line

Jump to the line is a secret feature in IntelliJ. It works, but developers don’t know about it. You need to install the Jump to Line plugin to use it. Since it has a relatively low install count, I assume people just don’t know it exists. Because this is a must-have plugin. It will change the way you debug!

With the jump to line, we can move the current instruction pointer to a different position in the method. We can drag the arrow on the left to bring execution to a new location. Notice that this works in both directions; I can move the current execution back and forth.

This doesn’t execute the code in between; it literally moves the current instruction to a new position. It’s so cool, and I have to show it again…

If you see a bug, just drag the execution back and reproduce it. You can change variable values and reproduce the issue over and over until you fully understand it.

We can skip over code that’s failing, etc. This is spectacular. I don’t need to recompile the code. If you ever had a case where you accidentally stepped over a line and oops. That’s not what I wanted. Then stopped the debugger and started from scratch. This is the plugin for you. This happened to everyone!

We can just drag the execution back and have a do-over. It’s absolutely fantastic!

Finally

In the next video, we will discuss the watch briefly. We will dig much deeper into it in the sixth video in the series. So stay tuned!

If you have any questions, please use the comments section. Thank you!

Debug code Execution (computing) Flow (web browser) intellij Instruction step

Published at DZone with permission of Shai Almog, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Ulyp: Recording Java Execution Flow for Faster Debugging
  • Error Handling Inside Kumologica Subflow
  • Techniques You Should Know as a Kafka Streams Developer
  • MuleSoft Parallel ForEach Processor vs. ForEach Processor

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!