স্ট্যাকট্রেসবিহীন জাভাতে নুলপয়েন্টারএক্সসেপশন


332

আমি আমাদের জাভা কোডটি ধরার উদাহরণ পেয়েছি NullPointerException, কিন্তু যখন আমি স্ট্যাকট্রেস (যা মূলত কলিংয়ের সমাপ্তি হয় Throwable.printStackTrace()) লগ ইন করার চেষ্টা করি তখন আমি যা পাই তা হ'ল:

java.lang.NullPointerException

এর বাইরে আর কেউ এসেছে? আমি "জাভা নাল পয়েন্টার খালি স্ট্যাক ট্রেস" এর জন্য গুগলিংয়ের চেষ্টা করেছি তবে এর মতো কিছুই আসে নি।


প্রসঙ্গটি কী? জড়িত আছে একাধিক থ্রেড? আমার একটি সুইং ওয়ার্কারে একটি ব্যতিক্রম স্ট্যাক ট্রেস পেতে চেষ্টা করার সমস্যা ছিল।
মাইকেল মায়ার্স

এখানে কোনও থ্রেডিং জড়িত নেই, কেবল সাধারণ পুরানো জাভা।
এডওয়ার্ড শার্ন

1
@ বোজো - নোপ - কীভাবে নলপয়েন্টারটি পুনরুত্পাদন করবেন তা নিশ্চিত নন।
এডওয়ার্ড শার্ন


-XX:-OmitStackTraceInFastThrowডুপটিতে আরও তথ্য : স্ট্যাকওভারফ্লো
ভাদজিম

উত্তর:


406

আপনি সম্ভবত হটস্পট জেভিএম ব্যবহার করছেন (মূলত সান মাইক্রোসিস্টেমস, পরে ওরেল কিনেছিলেন, ওপেনজেডিকে অংশ), যা প্রচুর অপ্টিমাইজেশন করে per স্ট্যাকের ট্রেসগুলি ফিরে পেতে, আপনাকে -XX:-OmitStackTraceInFastThrowজেভিএম-তে বিকল্পটি পাস করতে হবে ।

অপ্টিমাইজেশনটি হ'ল যখন প্রথমবারের জন্য একটি ব্যতিক্রম (সাধারণত একটি নলপয়েন্টার এক্সসেপশন) ঘটে তখন পুরো স্ট্যাক ট্রেসটি মুদ্রিত হয় এবং জেভিএম স্ট্যাক ট্রেসটিকে (বা সম্ভবত কোডের অবস্থান) স্মরণ করে। যখন এই ব্যতিক্রমটি প্রায়শই পর্যাপ্ত হয় তখন স্ট্যাক ট্রেস আর প্রিন্ট করা হয় না, উভয়ই ভাল পারফরম্যান্স অর্জনের জন্য এবং একই ধরণের স্ট্যাকের চিহ্ন সহ লগটিকে প্লাবিত না করার জন্য।

এটি কীভাবে হটস্পট জেভিএম এ প্রয়োগ করা হয় তা দেখতে এর একটি অনুলিপি ধরুন এবং বিশ্বব্যাপী চলকটি অনুসন্ধান করুন OmitStackTraceInFastThrowগতবার আমি কোডটি দেখেছি (2019), এটি ছিল গ্রাফকিট সিপিপি ফাইলটিতে


1
ভকভগক. এই বিকল্পটি পাস করার জন্য যদি কোনও লুকানো গোচাচা থাকে তবে কোনও ধারণা (যতক্ষণ না আমার অ্যাপ্লিকেশনটি এক টন ব্যতিক্রম ছোঁড়ে না ততক্ষণ এটি বেশ নিরীহ বলে মনে হয়)?
এডওয়ার্ড শার্ন

আমি জানি এমন কোনও গোপন ছাপ নেই। আপনি যখন হটস্পট উত্স কোডটি দেখেন, আপনি দেখতে পাবেন যে এই বিকল্পটি কেবলমাত্র এক জায়গায় ব্যবহৃত হয় (গ্রাফকিট কোডপিপি)। এবং এটি আমার কাছে দুর্দান্ত দেখাচ্ছে।
রোল্যান্ড ইলিগ

34
ভেবেছিলাম আমি অতিরিক্ত বিট যোগ করব যে স্ট্যাকের ট্রেসটি অপ্টিমাইজ হয়ে গেলে এটি কমপক্ষে একবারে সম্পূর্ণরূপে পরিচালিত হয়ে গেছে: জাভাস্পিক
//

1
আমি একটি ওপেনজেডিকে জেভিএম, সংস্করণ 1.8.0u171 (ডেবিয়ান 9) চালিয়ে যাচ্ছি এবং এটি -XX:-OmitStackTraceInFastThrowপতাকাটি গ্রহণ করার মতো বলে মনে হচ্ছে । আমি এখনও নিশ্চিত করতে পারি না যে সে কারণেই আমি স্ট্যাক-ট্রেসগুলি (যেমন, ব্যবহার করে e.printStackTrace) মুদ্রণ করতে ব্যর্থ হয়েছি , তবে এটি সম্ভবত খুব সম্ভবত বলে মনে হচ্ছে। এই আবিষ্কারটি প্রতিফলিত করার জন্য আমি উত্তরটি প্রসারিত করেছি।
ক্রিস ডাব্লু

আমাদের ক্ষেত্রে প্রথমে 125 টি ব্যতিক্রমের একটি স্ট্যাক ট্রেস ছিল এবং তারপরে লগ ফাইলের 3 টি রোটেশনের বাকী সমস্ত কিছুই ছিল না। এই উত্তরটি অপরাধীর সন্ধানে খুব সহায়ক ছিল।
সুখমেল

61

আপনি যেমন একটি মন্তব্যে উল্লেখ করেছেন, আপনি লগ 4 জে ব্যবহার করছেন। আমি লিখেছিলাম এমন একটি জায়গা (অজান্তেই) আবিষ্কার করেছি

LOG.error(exc);

সাধারণ পরিবর্তে

LOG.error("Some informative message", e);

অলসতার মধ্য দিয়ে বা সম্ভবত এটি সম্পর্কে চিন্তা না করা। এর দুর্ভাগ্যজনক অংশটি হ'ল এটি আপনার প্রত্যাশা মতো আচরণ করে না। লগার এপিআই আসলে বস্তুকে প্রথম যুক্তি হিসাবে গ্রহণ করে, স্ট্রিং নয় - এবং তারপরে এটি আর্গুমেন্টে স্ট্রিং () এ কল করে। সুতরাং সুন্দর সুন্দর স্ট্যাকের ট্রেস পাওয়ার পরিবর্তে, এটি কেবলমাত্র স্ট্রাস্টগুলি প্রিন্ট করে - যা এনপিইর ক্ষেত্রে বেশ অপব্যবহার্য।

আপনি সম্ভবত এটিই অনুভব করছেন?


+1: এটি বর্ণিত আচরণটি ব্যাখ্যা করবে এবং আপনি কেবল এটিই আবিষ্কার করেননি :)
পিটার ল্যাং

4
আমাদের উপরের প্রথম ফর্মটি কখনই ব্যবহার না করার একটি স্ট্যান্ডার্ড নীতি রয়েছে (LOG.error (exc);) - আমরা সবসময় 2 পরামিতি স্বাক্ষর ব্যবহার করি যাতে আমরা কেবল একটি কাঁচা স্ট্যাকট্রেসের পরিবর্তে লগগুলিতে কিছু বর্ণনামূলক বিবৃতি যুক্ত করি।
এডওয়ার্ড স্টার্ন

5
অবশ্যই, তবে নীতিটি এর অর্থ এই নয় যে এটি সর্বদা সঠিকভাবে কার্যকর করা হয়! অন্তত, এটি উল্লেখযোগ্য ছিল অনুমিত।
স্টিভেন শ্লানস্কার

সত্য, তবে এই ক্ষেত্রে এটি ছিল ;-)
এডওয়ার্ড শার্ন

28

আমরা অতীতেও একই আচরণ দেখেছি। দেখা গেল যে, কিছু পাগল কারণে, যদি কোনও নালপয়েন্টার এক্সেপশন একই জায়গায় কোডে একাধিকবার ঘটে থাকে, কিছুক্ষণ পরে Log.error(String, Throwable)সম্পূর্ণ স্ট্যাকের চিহ্নগুলি ব্যবহার করা বন্ধ করে দেয়।

আপনার লগ আরও পিছনে তাকানোর চেষ্টা করুন। আপনি অপরাধী খুঁজে পেতে পারেন।

সম্পাদনা: এই বাগটি প্রাসঙ্গিক বলে মনে হচ্ছে, তবে এটি এতদিন আগেই ঠিক করা হয়েছিল এটি সম্ভবত কারণ নয়।


2
বাগটি বন্ধ রয়েছে, তবে-এক্সএক্স: -অমিস্ট্যাকট্রেসইনফাস্টথ্রো পতাকাটি পারফরম্যান্স অপ্টিমাইজেশনের কাজ করার জন্য এখনও প্রয়োজন।
জোশুয়া গোল্ডবার্গ

আমি সম্প্রতি এটি অনেকগুলি দেখছি। এর কারণ কী হতে পারে বা কীভাবে এটি ঠিক করতে হবে সে সম্পর্কে কোনও সূত্র? লগিং সিস্টেমটি বেশ কয়েকদিন ধরে থাকতে পারে এবং প্রকৃত কারণটি ঘোরানো হয়েছে, ক্লান্তিকর অনুসন্ধানের কথা মনে নেই ...
পাভেল ভেসেলভ

5
পাভেল, আপনি -XX:-OmitStackTraceInFastThrowজোশুয়ার প্রস্তাবিত জেভিএম পতাকা ব্যবহার করে দেখেছেন? এছাড়াও stackoverflow.com/a/2070568/6198 দেখুন ।
ম্যাট সলনিট

1
এটা আমাদের জন্য ছিল। ধন্যবাদ।
অ্যান্ড্রু চিউং

20

এখানে একটি ব্যাখ্যা: হটস্পট উত্পাদনে তাদের স্ট্যাক ট্রেসগুলি এবং ফিক্সগুলি ব্যতিক্রম করে ব্যতিক্রম ঘটায়

আমি এটি ম্যাক ওএস এক্সে পরীক্ষা করেছি

  • জাভা সংস্করণ "1.6.0_26"
  • জাভা (টিএম) এসই রানটাইম এনভায়রনমেন্ট (1.6.0_26-b03-383-11A511 তৈরি করুন)
  • জাভা হটস্পট (টিএম) 64-বিট সার্ভার ভিএম (20.1-বি02-383, মিশ্র মোড তৈরি করুন)

    Object string = "abcd";
    int i = 0;
    while (i < 12289) {
        i++;
        try {
            Integer a = (Integer) string;
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

কোডের এই নির্দিষ্ট অংশের জন্য, 12288 পুনরাবৃত্তি (+ ফ্রিকোয়েন্সি?) এমন সীমা বলে মনে হচ্ছে যেখানে জেভিএম পূর্বনির্ধারিত ব্যতিক্রম ব্যবহার করার সিদ্ধান্ত নিয়েছে ...


10

exception.toString আপনাকে স্ট্যাকট্রেস দেয় না, এটি কেবল ফেরত দেয়

এই নিক্ষেপযোগ্য একটি সংক্ষিপ্ত বিবরণ। ফলাফলটি সংক্ষেপণ:

* the name of the class of this object
* ": " (a colon and a space)
* the result of invoking this object's getLocalizedMessage() method

exception.printStackTraceস্ট্যাকট্রেস আউটপুট করার পরিবর্তে ব্যবহার করুন ।


দুঃখিত, আমি আমার মূল পোস্টে ভুল বানান। আমি এগুলি Log4J এর মাধ্যমে লগ করছি যা প্রিন্টস্ট্যাকট্রেস () ব্যবহার করে।
এডওয়ার্ড শার্ন

1
getStackTrace()সমস্যাটি আপনার লগারের সাথে না রয়েছে তা নিশ্চিত করার জন্য আপনি কী ব্যবহার করার চেষ্টা করেছেন?
পিটার ল্যাং

1
আপনি যদি লগ 4 জ ব্যবহার করে থাকেন তবে লগ পদ্ধতিতে আর্গুমেন্টের অংশ হিসাবে ব্যতিক্রমটি অবশ্যই পাঠাতে ভুলবেন না। আমি এটি দিয়ে একটি উত্তর পোস্ট করব।
রবি ওয়ালাউ

@ গ্রাহ্য বৈধ পয়েন্ট! @ অ্যাডওয়ার্ড শার্ট: আপনি নিশ্চিত করতে পারবেন যে আপনি লগ 4 জ পদ্ধতির 2-আর্গ ফর্মটি অবশ্যই ব্যবহার করছেন? আমি জানি আপনি একটি উত্তরে আরও উল্লেখ করেছেন যে এটি করা কোম্পানির নীতি, তবে আপনি কি নিশ্চিত যে এই ক্ষেত্রে আপনি নীতি অনুসরণ করছেন?
KarstenF

এটি একটি দীর্ঘ শট হতে পারে, তবে এটি কি সম্ভব যে ব্যতিক্রমটি কোনও তৃতীয় পক্ষের কোড থেকে উদ্ভূত হয়েছে? হতে পারে এটি একটি (দুর্বল লিখিত) ব্যতিক্রম র‌্যাপার, যার ট্যাস্ট্রিং () কেবল মোড়ানো ব্যতিক্রমের শ্রেণীর নামটি দেয় এবং যা অন্তর্নিহিত স্ট্যাক ট্রেস সরবরাহ করতে ব্যর্থ হয়। আপনার ক্যাচ ব্লকে logger.info ("ব্যাতিক্রম শ্রেণি" "+ exc.class.getCanonicalName ()) এর মতো কিছু রাখার চেষ্টা করুন এবং দেখুন কী পান।
কার্সটেনএফ

4

বিকল্প প্রস্তাবনা - আপনি যদি একটিলপিস ব্যবহার করছেন তবে নালপয়েন্টার এক্সসেপশন নিজেই একটি ব্রেকপয়েন্ট নির্ধারণ করতে পারবেন (ডিবাগের দৃষ্টিকোণে "ব্রেকপয়েন্টস" ট্যাবে যান এবং এটিতে থাকা একটি ছোট আইকনে ক্লিক করুন!)

"ধরা" এবং "অপরিশোধিত" উভয় বিকল্পগুলি পরীক্ষা করে দেখুন - এখন আপনি যখন এনপিই ট্রিগার করবেন, আপনি তত্ক্ষণাত ব্রেকআপপয়েন্ট করবেন এবং তারপরে আপনি পদক্ষেপটি দেখতে পারবেন এবং ঠিক কীভাবে এটি পরিচালনা করা হচ্ছে এবং আপনি কেন স্ট্যাক ট্রেস পাচ্ছেন না।


1

toString()কেবল ব্যতিক্রম নাম এবং alচ্ছিক বার্তা দেয়। আমি ফোন করার পরামর্শ দেব

exception.printStackTrace()

বার্তাটি ডাম্প করার জন্য, বা আপনার যদি বিব্রত বিশদ প্রয়োজন হয়:

 StackTraceElement[] trace = exception.getStackTrace()

উপরে দেখুন - আমি ভুল বানান - আমি printStackTrace ব্যবহার করছি ()।
এডওয়ার্ড শার্ন

1

(আপনার কোডটি কল করছে কিনা printStackTrace()বা লগিং হ্যান্ডলারের দ্বারা এটি করা হচ্ছে কিনা সে বিষয়ে আপনার প্রশ্ন এখনও অস্পষ্ট ))

কী ঘটতে পারে সে সম্পর্কে এখানে কয়েকটি সম্ভাব্য ব্যাখ্যা রয়েছে:

  • ব্যবহৃত লগার / হ্যান্ডলারটি কেবল ব্যতিক্রমের বার্তার স্ট্রিং আউটপুট করতে কনফিগার করা হয়েছে, সম্পূর্ণ স্ট্যাক ট্রেস নয়।

  • আপনার অ্যাপ্লিকেশন (বা কিছু তৃতীয় পক্ষের লাইব্রেরি) লগ LOG.error(ex);4 জে লগার পদ্ধতির (উদাহরণস্বরূপ) 2-যুক্তি ফর্মের পরিবর্তে ব্যতিক্রমটি ব্যবহার করে লগ করছে ।

  • বার্তাটি অন্য কোথাও থেকে আসছেন যেখানে আপনি মনে করেন যে এটি; উদাহরণস্বরূপ এটি আসবে কিছু তৃতীয় পক্ষের গ্রন্থাগার পদ্ধতি, বা কিছু এলোমেলো জিনিস ডিবাগ করার আগের প্রচেষ্টা থেকে বাকি left

  • যে ব্যতিক্রমটি লগ করা হচ্ছে সেগুলি স্ট্যাকট্রেসকে অস্পষ্ট করার জন্য কিছু পদ্ধতি ওভারলোড করেছে। যদি এটি হয় তবে ব্যতিক্রমটি আসল নলপয়েন্টারএক্সসেপশন হবে না, তবে এটি এনপিইর কিছু কাস্টম সাব টাইপ বা এমনকি কিছু সংযোগযুক্ত ব্যতিক্রম।

আমি মনে করি যে শেষ সম্ভাব্য ব্যাখ্যাটি বেশ অসম্ভব, তবে লোকেরা কমপক্ষে বিপরীত প্রকৌশলকে "প্রতিরোধ" করার জন্য এই ধরণের কাজটি করার বিষয়ে চিন্তাভাবনা করে। অবশ্যই এটি সত্যই সৎ বিকাশকারীদের জীবনকে কঠিন করে তুলতে সফল হয়।


1

আপনি যখন আপনার প্রকল্পে AspectJ ব্যবহার করছেন, এমনটা হতে পারে যে কোনও দিক স্ট্যাকের ট্রেসের অংশটি আড়াল করে। উদাহরণস্বরূপ, আজ আমার ছিল:

java.lang.NullPointerException:
  at com.company.product.MyTest.test(MyTest.java:37)

মাভেনের নিশ্চিত ফায়ার এর মাধ্যমে পরীক্ষা চালানোর সময় এই স্ট্যাক ট্রেসটি মুদ্রিত হয়েছিল।

অন্যদিকে, ইন্টেলিজজে পরীক্ষা চলাকালীন, একটি পৃথক স্ট্যাক ট্রেস ছাপা হয়েছিল:

java.lang.NullPointerException
  at com.company.product.library.ArgumentChecker.nonNull(ArgumentChecker.java:67)
  at ...
  at com.company.product.aspects.CheckArgumentsAspect.wrap(CheckArgumentsAspect.java:82)
  at ...
  at com.company.product.MyTest.test(MyTest.java:37)

0

এটি ব্যতিক্রমটিকে আউটপুট দেবে, কেবলমাত্র ডিবাগ করতে আপনার ব্যবহার ব্যতীত আরও ভাল পরিচালনা করতে হবে।

import java.io.PrintWriter;
import java.io.StringWriter;
    public static String getStackTrace(Throwable t)
    {
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw, true);
        t.printStackTrace(pw);
        pw.flush();
        sw.flush();
        return sw.toString();
    }
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.