عرض عملي: استخدام مساعد لفهم stack trace ثم التحقق منه
في هذا الدرس 11 موضوعات
هذا الدرس متاح حاليًا باللغة الإنجليزية فقط، ولم تُنشر نسخته العربية بعد.
Lesson Overview
This lesson puts the whole module into one worked session. We take a real stack trace, write a hypothesis, ask an assistant using the four-part question, read the answer, catch a mistake in it, and settle the disagreement with the compiler, the documentation, and a run. It prepares you for the lab, where you will do the same on three bugs.
One honest note: the assistant's replies in this demo are scripted by the course to show typical behaviour, including one planned mistake. They are not output from a particular product. The Java code, the compiler messages, and the program output are real, from JDK 21.
Why this matters: this routine is the one you will use on the job, with or without an assistant. Reading a trace, forming a hypothesis, and proving or disproving it is the core debugging skill.
This lesson builds on all of BEG-056 (L01 to L04) and on reading stack traces from BEG-018.
Learning Objectives
By the end of this lesson you will be able to:
- Run a failing program and copy its full stack trace.
- Write a hypothesis from the trace before asking for help.
- Send a four-part question with no sensitive data.
- Restate an assistant's answer in your own words.
- Identify a hallucinated method using the compiler and the official documentation, and ask again with that evidence.
- Confirm the real cause with a run or the debugger, and write a short log entry for it.
Written Explanation
The six steps
The demo follows the routine from the earlier lessons.
- Run and copy the trace. Reproduce the failure and copy the complete trace, not a summary.
- Hypothesis first. Write what you think is wrong, where, and why.
- Ask with goal, code, exact error, and what you tried.
- Read and restate. Put the answer in your own words. If you cannot, that is a sign to ask a narrower question.
- Check every claim. Compile suggested code, read the documentation for new methods, and watch for answers that contradict the evidence.
- Confirm with the debugger or a test, and log it. Record your hypothesis, the answer, and the evidence that settled it.
Reading the trace
A Java stack trace has a first line with the exception type and message, then lines starting with at. The line that names your class and file is the best place to start, and the lines below it show the chain of calls that led there. Frames from java.base are Java's own code: the failure surfaced there, but your input or call usually caused it.
What a log entry looks like
For each bug, keep a short record:
Bug: <name>
My hypothesis: ...
Question sent: (the four parts)
Assistant's answer: (summary)
Evidence: compiler message / documentation sentence / debugger observation / test result
Outcome: confirmed / rejected / partly right (what was missing)This is exactly what the lab asks for, and it is the record a reviewer would find convincing.
Examples
Example 1: run the program and read the trace (simple)
A program averages grades read as text (imagine they came from a form). One entry has the letter O instead of the digit 0.
public class Avg {
static int parseGrade(String text) {
return Integer.parseInt(text);
}
static double average(String[] raw) {
int sum = 0;
for (String r : raw) sum += parseGrade(r);
return (double) sum / raw.length;
}
public static void main(String[] args) {
System.out.println(average(new String[] {"80", "90", "7O"}));
}
}Running it prints:
Exception in thread "main" java.lang.NumberFormatException: For input string: "7O"
at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:67)
at java.base/java.lang.Integer.parseInt(Integer.java:662)
at java.base/java.lang.Integer.parseInt(Integer.java:778)
at Avg.parseGrade(Avg.java:3)
at Avg.average(Avg.java:7)
at Avg.main(Avg.java:11)Read from the top: the exception is NumberFormatException with the offending text "7O". The first frame in our code is Avg.parseGrade(Avg.java:3), called from average line 7, called from main line 11.
Your hypothesis, written before asking: "Integer.parseInt rejects the text 7O because the last character is a letter, not a digit, so the crash is on the third element; the program does not handle bad input." (Line numbers in the Java frames can differ between Java versions.)
Example 2: ask, restate, and catch the planned mistake (practical)
The question you send:
Java 21, plain JDK.
Goal: average a list of grades that arrive as text.
Code: parseGrade and average (above, 9 lines).
Error: NumberFormatException: For input string: "7O"
at Avg.parseGrade(Avg.java:3) (full trace attached)
Tried: I think "7O" has a letter instead of zero. I have not
checked with the debugger.
Question: why does it fail, and how should the program handle bad text?Here is the scripted assistant reply:
parseIntfails because7Ois not a valid number. Java has a built-in safe parser, so replace line 3 withreturn Integer.tryParse(text);, which returnsnullfor bad input instead of throwing.
Restate in your own words: the first sentence matches your hypothesis. The second makes a claim you have not seen before: a built-in Integer.tryParse. A method you never met is exactly what to verify (L02). Compile it:
public class Avg2 {
public static void main(String[] args) {
System.out.println(Integer.tryParse("7O"));
}
}Avg2.java:3: error: cannot find symbol
System.out.println(Integer.tryParse("7O"));
^
symbol: method tryParse(String)
location: class Integer
1 errorThe Javadoc agrees: the parsing methods of Integer are parseInt, parseUnsignedInt, valueOf, and decode, and they report bad text by throwing NumberFormatException. tryParse is a hallucination; the confident tone was no evidence. Notice also what the reply missed: even with a safe parser, the program still needs a rule for what to do with the bad entry, and average divides by raw.length, which would include it.
You reply with the evidence: "The compiler says cannot find symbol: method tryParse(String) in class Integer, and the Javadoc has no such method. Please suggest a way to handle bad text using parseInt." The corrected answer suggests catching the exception, which you now understand because you read the documentation yourself.
Example 3: confirm the real cause, fix, and log (realistic)
First confirm the cause with the debugger rather than trusting either of us. (Menus differ between IntelliJ versions, so check your IDE's help.) Put a breakpoint in parseGrade at the parseInt line, with a condition such as text.equals("7O") if your IDE supports conditional breakpoints, run in debug mode, and inspect text. You should see the string 7O with a letter. Stepping into parseInt shows the exception being thrown for the non-digit character.
Now write the fix yourself. You decide: skip invalid entries, report them, and average only the valid ones; return 0 when there are none.
public class Avg3 {
static int parseGrade(String text) {
try {
return Integer.parseInt(text.trim());
} catch (NumberFormatException e) {
System.out.println("skipping invalid grade: \"" + text + "\"");
return -1;
}
}
static double average(String[] raw) {
int sum = 0;
int count = 0;
for (String r : raw) {
int g = parseGrade(r);
if (g >= 0) {
sum += g;
count++;
}
}
return count == 0 ? 0 : (double) sum / count;
}
public static void main(String[] args) {
System.out.println(average(new String[] {"80", "90", "7O"}));
System.out.println(average(new String[] {"x"}));
}
}skipping invalid grade: "7O"
85.0
skipping invalid grade: "x"
0.0The first run averages 80 and 90 only; the second proves an all-invalid input does not divide by zero. Using -1 as a marker is a simple choice; it works only because valid grades here are never negative. A different program might prefer a clearer design.
Your log entry:
Bug: grade average crash
Hypothesis: parseInt rejects "7O" (letter O), crash on element 3.
Assistant's answer: right cause; suggested Integer.tryParse (wrong).
Evidence: compiler "cannot find symbol: method tryParse(String)"; Javadoc
lists no tryParse; debugger showed text = "7O".
Outcome: partly right. Cause correct, fix invented; also missed the
divide-by-length issue. Fixed with try/catch and a count; tested.What settled the disagreement? The compiler, the documentation, and the debugger, not the assistant's confidence.
Backend Insight
In a backend service, "text that should be a number" arrives all the time: a query parameter (BEG-052), a JSON field, a database column imported from a file. Parsing and validating input at the edge, and deciding what the service does with bad input (reject, skip, or report), is routine work. Exceptions you read in a trace today become error responses and log lines later.
Your log entry is also a good habit for incidents: hypothesis, evidence, outcome. Teams write the same in bug tickets and post-incident notes.
Common Mistakes
Mistake 1: Trusting the first part of an answer because the second part was right
An answer can mix correct and invented claims. Check each claim you will use: the cause and the fix separately.
Mistake 2: Copying the fix without a hypothesis to compare against
Without your own guess you cannot judge whether the answer is right, incomplete, or off-topic.
Mistake 3: Letting the assistant decide design questions
What to do with bad input (skip, reject, stop) is your decision, based on what the program is for. An assistant can list options; it cannot know your requirements.
Mistake 4: Not recording the wrong answer
The log of where an assistant failed is what teaches you when to trust it. Write it down.
Exercises
Try each exercise yourself before opening the solutions.
Level A: Foundation
A1. In the trace of Example 1, which line is the first one in our own code?
أظهر الحل A1
A1. Avg.parseGrade(Avg.java:3); the java.base lines above it are Java's own code where the failure surfaced.
A2. Name the six steps of the demo routine.
أظهر الحل A2
A2. Run and copy the trace; write a hypothesis; ask with the four parts; read and restate the answer; check every claim; confirm with the debugger or a test and write the log entry.
A3. What three things settled the disagreement about tryParse?
أظهر الحل A3
A3. The compiler (cannot find symbol: method tryParse(String)), the documentation (no such method in Integer), and the debugger or run that showed the real cause.
Level B: Application
B1. Run Integer.parseInt("") in a scratch program (or reason from the Javadoc). Which exception do you expect, and why does the documentation make that prediction possible?
أظهر الحل B1
B1. Expect NumberFormatException. The Javadoc for parseInt says it throws that exception when the string is null or has length zero, among other cases, so an empty string fails. Running it on JDK 21 printed NumberFormatException: For input string: "".
B2. An assistant says String.isNumeric() can test whether text is a number. Describe, in three steps, how you would check this claim, and what result you expect.
أظهر الحل B2
B2. (1) Search the Javadoc of String for isNumeric. (2) Compile a one-line call, "123".isNumeric(). (3) Read the compiler message. Expected, and what JDK 21 reported: cannot find symbol, symbol: method isNumeric(), location: class String. Check it yourself rather than taking this on trust.
B3. Write the "Hypothesis" and "Evidence" lines of a log entry for a bug where average of an empty array throws ArithmeticException: / by zero.
أظهر الحل B3
B3. Hypothesis: "grades.length is 0 for the empty array, so the division on the return line fails." Evidence: the trace names Div.average(Div.java:5); the debugger shows grades.length == 0 at that line.
Level C: Challenge
C1. The Avg3 code treats any negative number as "invalid" because of the -1 marker. Find a case where that marker design gives a wrong result, and propose a cleaner approach that uses only what you have learned.
أظهر الحل C1
C1. A valid grade is never negative here, so -1 works, but if the program later accepts negative adjustments or scores, valid negative values would be skipped silently. Cleaner options: have parseGrade return an Integer that is null for invalid text and test for null, or return a boolean from a separate method such as isValidGrade(String) that uses try/catch, so no number is overloaded as a flag.
C2. Write a four-line follow-up message to an assistant that rejects a hallucinated method, includes the evidence, and asks for an alternative.
أظهر الحل C2
C2. For example: "I tried your suggestion. The compiler says cannot find symbol: method tryParse(String) in class Integer, and the Javadoc lists no such method. Please do not use methods you are not sure exist. What is the documented way to handle bad text with parseInt?"
Mini Challenge
Choose one bug from the BEG-018-LAB1 bug hunt. Perform steps 1 to 6 and write the log entry in the format shown. Deliberately write down one thing you will check in the assistant's answer even if it sounds right, and say how you will check it.
Check your work: the hypothesis predates the question; the question has all four parts and no sensitive data; at least one claim was checked by the compiler, the documentation, or the debugger; and the log shows the outcome (confirmed, rejected, or partly right).
Summary & Next Lesson
Key takeaways
- Copy the full trace, then write your hypothesis before asking.
- Restate the answer in your own words and check each claim you will use.
- A confident answer can mix a right cause with an invented method.
- The compiler, the official documentation, and the debugger settle disagreements, not tone.
- Make the design decision yourself, test the fix, and log hypothesis, answer, and evidence.
Next lesson
This was the last lesson of the module. Next, the lab "Explain, don't copy" (BEG-056-LAB1) has you apply this routine to three bugs from BEG-018-LAB1, including one case where the assistant was wrong or incomplete.
Self-check
- Why write a hypothesis before asking?
- What did the compiler say about
Integer.tryParse? - Name two sources of evidence besides the assistant's own words.
- Why was the first assistant answer "partly right"?
- What goes into a log entry?
أظهر الإجابات
- It gives you something to compare the answer with, and shows what you already understand.
cannot find symbol, withsymbol: method tryParse(String)andlocation: class Integer.- Any two of: the compiler, the official documentation, the debugger, a test or a run.
- It found the real cause (bad text for
parseInt) but suggested a method that does not exist and ignored the effect on the average. - The bug, your hypothesis, the question sent, the answer, the evidence, and the outcome.
References
- Oracle, Java SE 21
IntegerJavadoc. Supports thatIntegerhas notryParse, that its parsing methods signal bad input withNumberFormatException, and the conditions under whichparseIntthrows it (null or empty string, non-digit character). - OWASP GenAI Security Project, LLM09:2025 Misinformation. Supports that models can produce credible but false output, including references to code libraries that do not exist.
- The scripted assistant replies, the log format, and the programs are this course's own. The compiler messages, traces, and outputs are real, from JDK 21. The
parseInt("")and"123".isNumeric()results were also confirmed by running them; I did not fetch theStringJavadoc.
التطبيق
طبّق هذا الدرس بمختبر الوحدة وتمارينها واختبارها.
تعليم الدرس كمكتمل اختياري ويمكنك التراجع عنه في أي وقت. يبقى تقدمك محفوظًا في هذا المتصفح.