- Which debugging setup is most appropriate?
Answer: Place a conditional line breakpoint inside the loop using record.getId() == 4172 && attempts > 2.
When debugging a loop with thousands of iterations, the key concept being tested is conditional breakpoints — a feature in modern IDEs (IntelliJ, Eclipse, VS Code) that lets you pause execution only when a specific logical condition evaluates to true. Recognizing when brute-force debugging is impractical should immediately make you think: "I need a smarter breakpoint."
Option D is correct because it places a line breakpoint inside the loop with the exact condition record.getId() == 4172 && attempts > 2. The debugger skips all 10,000 iterations silently and suspends execution only at the precise moment both conditions are met — giving you full access to program state right before the defect manifests. This is exactly what a conditional breakpoint is designed for.
Option A fails because a breakpoint after the loop means the defective iteration has already completed. You'd be inspecting state too late, and a watch expression alone doesn't control when execution pauses. Option B is technically possible but painfully impractical — manually resuming thousands of times is exactly the scenario the question warns against, and you might even overshoot the target iteration. Option C introduces a method breakpoint on getId, which will suspend on every call to that method across all 10,000 records, making it nearly as slow as B and offering no filtering logic.
As a study tip, whenever a question describes a large dataset with a defect triggered by a specific combination of conditions, your instinct should be to reach for a conditional breakpoint. Memorize the syntax: most IDE conditional breakpoints accept any valid boolean expression from your program's scope.
- How should the run configuration be changed?
Answer: Put -Dtrace=true in VM options and put input.txt in the Program arguments field.
When configuring a Java application in an IDE, you need to distinguish between two fundamentally different types of command-line input: JVM arguments and program arguments. JVM arguments (like system properties set with -D) are consumed by the Java Virtual Machine before your program runs. Program arguments are what gets passed into your main(String[] args) array and are consumed by your application code.
Boolean.getBoolean("trace") reads a system property, which must be set via a -D JVM flag. That flag belongs in the VM options field of your run configuration — not in Program arguments. args[0] is populated from the Program arguments field, so input.txt belongs there. Placing -Dtrace=true in VM options and input.txt in Program arguments (option B) correctly routes each value to where the JVM and your code expect to find it.
A is wrong because input.txt is a program argument, not a VM option, and the working-directory field controls the file system path from which the app runs — it has nothing to do with passing arguments. C is wrong because input.txt is not a JVM argument at all; listing it in VM options would confuse the JVM, and ordering doesn't fix that fundamental mismatch. D is wrong because reversing the order within Program arguments doesn't help — -Dtrace=true will still land in args[0] and be treated as a file name, while system properties remain unset.
A useful rule of thumb: anything starting with -D is a JVM system property and belongs in VM options; everything your main method reads from args[] belongs in Program arguments.
- Which action most directly corrects the problem while preserving both main classes?
Answer: Edit the run configuration to use com.example.Main with the server module on its runtime classpath.
When an IDE runs your application, it doesn't just compile your code — it uses a run configuration that specifies which main class to launch and which module's classpath to use. These are separate settings, and misunderstanding this separation is exactly the trap this question sets.
The root cause here is that the run configuration still points to the client module's com.example.Main, regardless of which file you just edited. Since both modules have a class with the identical fully-qualified name, the runtime classpath determines which one actually executes. Editing and rebuilding only changes the compiled output — it never touches the run configuration. The fix, then, is B: update the run configuration to reference com.example.Main with the server module on its classpath. This directly tells the JVM which version of the class to load at runtime, solving the problem without touching either class.
A is a red herring. Renaming the server class would technically let the IDE discover it, but it changes the server class rather than preserving both main classes — violating the constraint in the question. C makes things worse: adding client as a dependency of server creates an unnecessary coupling between modules, and still doesn't tell the run configuration to launch the server's main method. D is a diagnostic action, not a corrective one. Debug mode with a breakpoint helps you observe behavior, but it doesn't change which main class gets launched.
As a study tip: whenever a question involves a program running the "wrong" class despite correct code, your first instinct should be to check the run configuration, not the source files or build output.
- Which IDE setting should be corrected first?
Answer: Set the project's or module's SDK and language level to Java 17, then rebuild the project.
When an IDE reports that a language feature like records "is not supported at source level 11," you're looking at a compilation configuration problem, not a runtime or debugging problem. IDEs manage several independent settings — the project SDK, the language/source level, the run configuration JRE, and the debugger — and they don't automatically sync with each other just because Java 17 is installed on your machine.
The fix is C: setting the project's (or module's) SDK and language level to Java 17, then rebuilding. The compiler uses the project/module SDK and language level to determine which syntax is valid. If that's set to Java 11, the compiler rejects records regardless of what Java version your terminal or run configuration points to. Once you correct the SDK and language level, the compiler will accept Java 17 features and the error disappears.
A is wrong because debugger stepping filters control which classes the debugger steps into during execution — they have no influence over compilation or which language features the compiler accepts. B is wrong because compilation does not inherit the run configuration's JRE. The run configuration controls which JVM runs your already-compiled bytecode; the compiler is governed separately by the project/module settings. D is wrong because the JDK is not a library dependency you add to the classpath — that's for third-party jars. The JDK is configured as the project SDK, and adding it as a classpath entry won't change the source level the compiler enforces.
As a study tip: when you see a compile-time language-feature error in an IDE, always look at the project/module SDK and language level first — that's the authoritative setting for the compiler.
- Which change provides a stable snapshot of the shared state at that breakpoint?
Answer: Change the breakpoint's suspend policy to pause all threads when the breakpoint is reached.
When debugging multithreaded programs, the core challenge is visibility: if other threads keep running while you inspect shared state, the values you see are a moving target. The question is asking you to identify which debugger configuration freezes the entire program's state — not just one thread.
Changing the breakpoint's suspend policy to pause all threads (option D) is exactly that fix. When the breakpoint is hit, the JVM halts every thread simultaneously, giving you a consistent, stable snapshot of the shared counter. Nothing can modify it while you inspect it.
Option A is a misconception about logpoints. Logpoints record a value at a moment in time, but they don't pause execution — other threads continue running freely, so the underlying state still changes after the log entry is written.
Option B misunderstands conditional breakpoints. A condition like "counter >= 0" only controls when the breakpoint triggers — it has no effect on which threads are suspended once it does fire. The suspend policy remains unchanged, so the same instability persists.
Option C conflates Step Into with thread control. "Step Into" navigates through the current thread's call stack one method at a time; it has no authority to pause or synchronize other independent threads. Other worker threads continue executing unaffected.
The key strategy here: always separate when a breakpoint fires (conditions, hit counts) from what it suspends (suspend policy). On exam questions about thread-safe debugging, look for the option that addresses the suspend policy — that's the only lever that controls which threads halt.
- Which debugger configuration best satisfies this requirement?
Answer: Create an exception breakpoint for IllegalArgumentException set to suspend on thrown exceptions, including caught ones.
When debugging in Java, you'll sometimes need to intercept exceptions at the exact moment they're thrown — before any catch block handles them. This is where exception breakpoints shine, and that's the core concept being tested here.
Modern Java debuggers (like IntelliJ IDEA or Eclipse) let you configure exception breakpoints that trigger the moment a specified exception type is thrown, regardless of where in the code that happens. Crucially, you can configure them to suspend on caught exceptions as well, not just uncaught ones. Answer A describes exactly this setup — an exception breakpoint targeting IllegalArgumentException with "suspend on thrown, including caught" enabled. The debugger halts at the precise throw site before the catch block ever runs, which is exactly what the developer needs.
B is wrong because placing a breakpoint on the logging statement pauses execution after the catch block has already handled the exception — you've missed the throw site entirely and lost its original stack context. C contains a dangerous misconception: caught exceptions do not automatically suspend at their throw sites. Configuring suspension for uncaught exceptions only would miss every IllegalArgumentException that the service successfully catches, which is precisely the scenario described. D is ineffective because a method breakpoint on the enclosing method pauses at method entry, potentially far before the exception is thrown, and gives you no direct visibility into which statement caused it.
As a study tip, remember: exception breakpoints are the right tool whenever you need to intercept an exception at the throw site without knowing the source line in advance — especially when the exception is caught and swallowed somewhere downstream.
- What should the developer do next to make the IDE pause at the breakpoint?
Answer: Launch the same run configuration with Debug rather than Run, leaving the enabled breakpoint in place.
Whenever you see a question about debugging in Java, the first thing to ask yourself is: what mode is the application running in? IDEs like IntelliJ IDEA and Eclipse have two distinct launch modes — Run and Debug — and breakpoints are only honored in Debug mode.
When you launch with the standard Run command, the JVM executes your code at full speed with no debugging agent attached. The IDE has no mechanism to intercept execution, so even a perfectly configured breakpoint is silently ignored. The fix is exactly what A describes: use the Debug launch command (often a bug icon) with the same run configuration. This starts the JVM with the JDWP (Java Debug Wire Protocol) agent, which allows the IDE to communicate with the running process and pause at breakpoints.
B is wrong because breakpoints absolutely can be placed on executable statements inside a method body — that's the most common place to put them. Method declarations themselves are not executable lines.
C is a misconception about how debuggers attach. Debug mode attaches the debugging agent at JVM startup, before any of your code runs. There is no race condition to solve with Thread.sleep.
D is entirely fabricated. Breakpoints do not "activate" after a first run, and rebuilding in Run mode has no special effect on breakpoint behavior. This is a trap for students who confuse build issues with launch-mode issues.
The key study tip: if your breakpoints are being skipped, always check your launch mode first — it's the most common cause and the easiest fix.
- What is the best debugging approach?
Answer: Use a non-mutating inspection such as queue.peek() or expand the queue in the Variables view.
When debugging, the key distinction to understand is the difference between mutating and non-mutating operations. A mutating operation changes the underlying data structure, while a non-mutating one simply reads it. Evaluating expressions in a debugger executes real code — it doesn't simulate or sandbox the call — so calling queue.remove() during a debug session actually removes the element, permanently altering state before your program resumes.
The correct approach is B: use a non-mutating inspection method. queue.peek() returns the head element without removing it, leaving the queue exactly as it was. Alternatively, expanding the queue object in the Variables view lets you visually inspect its contents without executing any code at all. Both approaches give you the information you need without side effects.
A is based on a misconception — disabling breakpoints has no effect on whether an evaluated expression mutates data. Breakpoints control where execution pauses, not whether evaluated code has side effects. C is entirely fictional; no such "auto-restore" mechanism exists in Java debuggers. Switching from Debug to Run mode simply resumes execution without debugging features — it does nothing to undo a prior mutation. D is also wrong because Step Over advances the program counter to the next line; it doesn't discard or undo mutations that have already occurred in the debugger's expression evaluator.
As a study tip: whenever a debugging question involves inspecting a collection, ask yourself "does this operation change state?" Prefer peek(), get(), or the Variables/Watches view over any method that removes or modifies elements — safe inspection is always the goal.
- Which debugger command best matches this goal?
Answer: Step Over, because it executes the call without entering it and pauses at the next source line.
When debugging in Java, it helps to picture yourself as the program's navigator: you decide how much of the code to execute before pausing again. The three core stepping commands — Step Into, Step Over, and Step Out — each give you a different level of granularity, and the scenario here is a classic test of knowing which one respects method boundaries.
The goal is to let calculate(order) run completely and land on the next line without ever entering calculate or any methods it calls internally. That is exactly what Step Over (C) does — it treats the method call as a single unit, executes it behind the scenes, and pauses at the following source line where you can inspect total.
A is wrong because Step Into does the opposite of what's wanted: it follows execution inside calculate, pausing at its first statement. That forces you to manually step through every line of the method.
B describes Step Out, which is useful when you've already entered a method and want to finish it and return to the caller. Here, execution hasn't entered calculate yet, so Step Out would finish the current method (the one containing this line) — not calculate.
D is tempting but incorrect. Resume (or Continue) runs the program freely until it hits the next breakpoint. If no breakpoint exists after the assignment, execution won't pause at all — there's no guarantee of stopping on the next line.
A handy memory trick: Over = skip over the method body, Into = dive in, Out = climb back up. Match the verb to the direction you want to travel through the call stack.
- Which change most directly makes the IDE launch behave like the terminal launch?
Answer: Set the run configuration's working directory to the project root while keeping the same relative path.
When Java resolves a relative file path like config/settings.properties, it looks for that path starting from the current working directory — the directory the JVM was launched from, not where the .class files live. This is the core concept being tested here.
In a terminal, you run the program from the project root, so config/settings.properties resolves correctly. The IDE, however, sets its working directory to the build-output folder by default. That folder has no config/ subdirectory, so the JVM can't find the file — even though it exists in your project. The fix is straightforward: configure the IDE's run configuration to use the project root as the working directory. Now both environments resolve the same relative path from the same starting point. That's exactly what A does, and it's the most direct solution.
B is a common trap. Adding a directory to the classpath helps when you're loading resources through the classloader (e.g., getResourceAsStream), not when you're using new File(...) or Path.of(...) with a relative path. Classpath and working directory are completely separate concepts. C is incorrect because the JDK installation directory has nothing to do with relative path resolution — the working directory is set by the launch environment, not the SDK version. D is a distractor with no technical basis; Debug mode changes how the JVM handles breakpoints and bytecode, not how the OS resolves file paths.
As a study tip, remember the rule: relative paths resolve from the working directory, not the classpath, not the JDK, not the source folder. Whenever you see a NoSuchFileException that seems mysterious, check your working directory first.