স্ট্যাকট্রেস বা প্রতিবিম্ব ব্যবহার করে কোনও পদ্ধতির কলারকে কীভাবে খুঁজে পাব?


390

আমার একটি পদ্ধতির কলার সন্ধান করা উচিত। স্ট্যাকট্রেস বা প্রতিবিম্ব ব্যবহার করে কি এটি সম্ভব?


5
শুধু ভাবছি, তবে কেন আপনার এটি করা দরকার?
জুলিয়েট

2
আমার একটি বিজ্ঞপ্তিপ্রাপ্ত ইভেন্ট সহ একটি প্যারেন্ট ক্লাস (এমভিসি মডেল) আছে এবং আমার সাবক্লাসের কেবলমাত্র সেটটাররা এই পদ্ধতিটিকে কল করে। আমি আমার কোডটি একটি অপ্রয়োজনীয় যুক্তি দিয়ে লিটার করতে চাই না। আমি বরং অভিভাবক শ্রেণীর পদ্ধতিটিকে সেটারটি বের করে দেখি that
সতীশ

30
@ সতীশ সাউন্ডসের মত আপনার মতামতটি আবার চিন্তা করা উচিত
ক্রোসনভোল্ড

7
@ জুলিয়েট একটি বিশাল সংখ্যক কোডকে রিফেক্টর করার অংশ হিসাবে সম্প্রতি আমি একটি পদ্ধতি পরিবর্তন করেছি যা অনেক কিছুই ব্যবহার করে। কোডটি নতুন পদ্ধতিটি সঠিকভাবে ব্যবহার করছে কিনা তা সনাক্ত করার একটি নির্দিষ্ট উপায় রয়েছে, তাই আমি ক্লাস এবং লাইন নম্বরটি মুদ্রণ করছিলাম যা এই ক্ষেত্রে এটি বলে। লগিংয়ের বাইরে, আমি এই জাতীয় কোনও কিছুর আসল উদ্দেশ্য দেখতে পাচ্ছি না। যদিও আমি এখনই এপিআই-র লিখতে চাই DontNameYourMethodFooExceptionযা কলিং পদ্ধতির নাম দেওয়া হয় ফুও throw
ক্রંચার

5
আমি আমার পদ্ধতির কলারকে একটি অমূল্য ডিবাগিং সরঞ্জাম পেতে সক্ষম হতে পেয়েছি: যা ওয়েব অনুসন্ধান আমাকে এখানে এনেছিল। যদি আমার পদ্ধতিটি একাধিক স্থান থেকে কল করা হচ্ছে, তবে কি সঠিক সময়ে সঠিক অবস্থান থেকে কল করা হচ্ছে? ডিবাগিং বা লগিংয়ের বাইরে, কার্যকারিতা সম্ভবত সর্বোপরি সীমাবদ্ধ যেমন @ ক্র্যাঙ্কার উল্লেখ করেছেন।
ওগ্রে গীতসংহিতা 33

উত্তর:


412
StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace()

জাভাডোকস অনুসারে:

অ্যারের শেষ উপাদানটি স্ট্যাকের নীচে প্রতিনিধিত্ব করে, যা ক্রমটিতে সাম্প্রতিকতম পদ্ধতির প্রার্থনা method

একজন StackTraceElementআছে getClassName(), getFileName(), getLineNumber()এবং getMethodName()

আপনি কোন সূচকটি চান তা নির্ধারণ করতে আপনাকে পরীক্ষা করতে হবে (সম্ভবত stackTraceElements[1]বা [2])।


7
আমার লক্ষ্য করা উচিত যে getStackTrace () এখনও একটি ব্যতিক্রম তৈরি করে, তাই এটি সত্যিই দ্রুত নয় - কেবল আরও সুবিধাজনক।
মাইকেল মায়ার্স

41
নোট করুন যে এই পদ্ধতিটি আপনাকে কলার দেবে না, কেবল কলারের ধরণ । আপনার পদ্ধতিতে কল করে থাকা অবজেক্টটির কোনও রেফারেন্স আপনার কাছে নেই।
জোছিম সৌর

3
কেবল একটি পার্শ্ব নোট, তবে 1.5 জেভিএম থ্রেড.কন্ট্রেনথ্রেড ()। GetStackT્રેસ () একটি নতুন এক্সেপশন () (প্রায় 3 গুণ ধীর) তৈরির চেয়ে অনেক ধীর বলে মনে হচ্ছে। তবে ইতিমধ্যে উল্লিখিত হিসাবে, আপনি কোনওভাবেই পারফরম্যান্স-সমালোচনামূলক ক্ষেত্রে এই জাতীয় কোড ব্যবহার করা উচিত নয়। ;) একটি 1.6 জেভিএম কেবল 10% কম ধীর বলে মনে হচ্ছে এবং যেমন সফ্টওয়্যার বানর বলেছে, এটি "নতুন ব্যতিক্রম" পদ্ধতির চেয়ে অভিপ্রায়টিকে আরও ভালভাবে প্রকাশ করে।
গাজেড

21
@ ইলকো থ্রেড.কমেরথ্রেড () সস্তা। থ্রেড.গেটস্ট্যাক ট্রেস () ব্যয়বহুল কারণ থ্রোয়েবল.ফিলআইনস্ট্যাকট্রেস () এর বিপরীতে, পদ্ধতিটি একই থ্রেডটি যা পরীক্ষা করছে তা বলেছে তার কোন গ্যারান্টি নেই, সুতরাং জেভিএমকে একটি "সাফপয়েন্ট" তৈরি করতে হবে - গাদা এবং স্ট্যাকটি লক করা। এই বাগের প্রতিবেদনটি দেখুন: bugs.sun.com/bugdatedia/view_bug.do?bug_id=6375302
ডেভিড মোলস

7
@ জোয়াচিমসৌয়ার কী জানেন যে পদ্ধতিটি কল করার উদ্দেশ্যে কোনও রেফারেন্স পাওয়ার কোনও উপায় আপনি জানেন?
জোফদে

216

একটি মন্তব্যে একটি বিকল্প সমাধান পাওয়া যাবে বর্ধনের জন্য এই অনুরোধটির । এটি getClassContext()একটি কাস্টম পদ্ধতি ব্যবহার করে SecurityManagerএবং স্ট্যাক ট্রেস পদ্ধতির চেয়ে দ্রুত বলে মনে হয়।

নিম্নলিখিত প্রোগ্রামটি বিভিন্ন প্রস্তাবিত পদ্ধতির গতি পরীক্ষা করে (সবচেয়ে আকর্ষণীয় বিটটি অভ্যন্তরীণ শ্রেণীর মধ্যে রয়েছে SecurityManagerMethod):

/**
 * Test the speed of various methods for getting the caller class name
 */
public class TestGetCallerClassName {

  /**
   * Abstract class for testing different methods of getting the caller class name
   */
  private static abstract class GetCallerClassNameMethod {
      public abstract String getCallerClassName(int callStackDepth);
      public abstract String getMethodName();
  }

  /**
   * Uses the internal Reflection class
   */
  private static class ReflectionMethod extends GetCallerClassNameMethod {
      public String getCallerClassName(int callStackDepth) {
          return sun.reflect.Reflection.getCallerClass(callStackDepth).getName();
      }

      public String getMethodName() {
          return "Reflection";
      }
  }

  /**
   * Get a stack trace from the current thread
   */
  private static class ThreadStackTraceMethod extends GetCallerClassNameMethod {
      public String  getCallerClassName(int callStackDepth) {
          return Thread.currentThread().getStackTrace()[callStackDepth].getClassName();
      }

      public String getMethodName() {
          return "Current Thread StackTrace";
      }
  }

  /**
   * Get a stack trace from a new Throwable
   */
  private static class ThrowableStackTraceMethod extends GetCallerClassNameMethod {

      public String getCallerClassName(int callStackDepth) {
          return new Throwable().getStackTrace()[callStackDepth].getClassName();
      }

      public String getMethodName() {
          return "Throwable StackTrace";
      }
  }

  /**
   * Use the SecurityManager.getClassContext()
   */
  private static class SecurityManagerMethod extends GetCallerClassNameMethod {
      public String  getCallerClassName(int callStackDepth) {
          return mySecurityManager.getCallerClassName(callStackDepth);
      }

      public String getMethodName() {
          return "SecurityManager";
      }

      /** 
       * A custom security manager that exposes the getClassContext() information
       */
      static class MySecurityManager extends SecurityManager {
          public String getCallerClassName(int callStackDepth) {
              return getClassContext()[callStackDepth].getName();
          }
      }

      private final static MySecurityManager mySecurityManager =
          new MySecurityManager();
  }

  /**
   * Test all four methods
   */
  public static void main(String[] args) {
      testMethod(new ReflectionMethod());
      testMethod(new ThreadStackTraceMethod());
      testMethod(new ThrowableStackTraceMethod());
      testMethod(new SecurityManagerMethod());
  }

  private static void testMethod(GetCallerClassNameMethod method) {
      long startTime = System.nanoTime();
      String className = null;
      for (int i = 0; i < 1000000; i++) {
          className = method.getCallerClassName(2);
      }
      printElapsedTime(method.getMethodName(), startTime);
  }

  private static void printElapsedTime(String title, long startTime) {
      System.out.println(title + ": " + ((double)(System.nanoTime() - startTime))/1000000 + " ms.");
  }
}

আমার 2.4 গিগাহার্টজ ইন্টেল কোর 2 ডুও ম্যাকবুক জাভা 1.6.0_17 চলমান থেকে আউটপুটটির একটি উদাহরণ:

Reflection: 10.195 ms.
Current Thread StackTrace: 5886.964 ms.
Throwable StackTrace: 4700.073 ms.
SecurityManager: 1046.804 ms.

অভ্যন্তরীণ প্রতিচ্ছবি পদ্ধতি অন্যদের তুলনায় অনেক দ্রুত। নতুন তৈরি Throwableহওয়া থেকে স্ট্যাক ট্রেস পাওয়া বর্তমানের থেকে পাওয়ার চেয়ে দ্রুত Thread। এবং কলার শ্রেণীর সন্ধানের অভ্যন্তরীণ উপায়গুলির মধ্যে কাস্টমটি SecurityManagerদ্রুততম বলে মনে হয়।

হালনাগাদ

এই মন্তব্যটিতে লাইওমি পয়েন্ট হিসাবে উল্লেখ করেছেনsun.reflect.Reflection.getCallerClass() পদ্ধতি জাভা 7 আপডেট 40 ডিফল্টরূপে অক্ষম এবং এই সম্পর্কে আরো জাভা 8. পড়ুন সম্পূর্ণভাবে সরিয়ে ফেলা হয়েছে জাভা বাগ ডাটাবেসের মধ্যে এই সমস্যা

আপডেট 2

হিসাবে zammbi খুঁজে পেয়েছে, ওরাকল ছিল পরিবর্তনের আউট ব্যাক করতে বাধ্য অপসারিতsun.reflect.Reflection.getCallerClass() । এটি জাভা 8 এ এখনও উপলব্ধ (তবে এটি অবনমিত হয়)।

আপডেট 3

3 বছর পরে: বর্তমান জেভিএমের সাথে সময় নির্ধারণের বিষয়ে আপডেট।

> java -version
java version "1.8.0"
Java(TM) SE Runtime Environment (build 1.8.0-b132)
Java HotSpot(TM) 64-Bit Server VM (build 25.0-b70, mixed mode)
> java TestGetCallerClassName
Reflection: 0.194s.
Current Thread StackTrace: 3.887s.
Throwable StackTrace: 3.173s.
SecurityManager: 0.565s.

5
হ্যাঁ, এটি মনে হয়। তবে মনে রাখবেন যে আমি উদাহরণটিতে যে সময়টি দিচ্ছি তা মিলিয়ন কলের জন্য - তাই আপনি কীভাবে এটি ব্যবহার করছেন তার উপর নির্ভর করে এটি কোনও সমস্যা নাও হতে পারে।
জোহান কাভিং

1
আমার জন্য আমার প্রকল্প থেকে প্রতিবিম্ব অপসারণ 10 গতি বৃদ্ধি পেয়েছে।
কেভিন পার্কার

1
হ্যাঁ, সাধারণভাবে প্রতিফলন ধীর (দেখুন উদাঃ stackoverflow.com/questions/435553/java-reflection-performance ), কিন্তু এই নির্দিষ্ট অভ্যন্তরীণ sun.reflect.Reflection বর্গ ব্যবহার ক্ষেত্রে দ্রুততম হয়।
জোহান কাভিং

1
এটি আসলে প্রয়োজন নেই। ফিরে আসা ক্লাসনেমটি মুদ্রণের জন্য আপনি উপরের কোডটি সংশোধন করে এটি যাচাই করতে পারেন (এবং আমি লুপ সংখ্যাটি 1 এ হ্রাস করার পরামর্শ দিচ্ছি)। আপনি দেখতে পাবেন যে সমস্ত পদ্ধতি একই শ্রেণীর নাম - টেস্টজেটকলারক্লাসনেম ফেরত দেয়।
জোহান কাভিং

1
getCallerClass অবমানিত এবং 7u40 এ সরানো হবে .. দু: খ :(
লাইওমি

36

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


6
++ কলার জানা খুব বেশি তথ্য। যদি আপনার অবশ্যই হয়, আপনি একটি ইন্টারফেসে পাস করতে পারেন, তবে একটি বড় সম্ভাবনা রয়েছে যে একটি বড় রিফ্যাক্টরিং প্রয়োজন। @ সতীশের উচিত তার কোড পোস্ট করা এবং এটির সাথে কিছু মজা করা যাক :)
বিল কে

15
এটি করতে চাওয়ার বৈধ কারণগুলি। আমি কয়েকটি অনুষ্ঠান করেছি যেখানে উদাহরণস্বরূপ পরীক্ষার সময় এটি সহায়ক হয়েছিল।
Eelco

2
@ চিলেনিয়াস আমি জানি :) আমি LoggerFactory.getLogger(MyClass.class)ক্লাস আক্ষরিক যেখানে পাস করতে হবে না এমন একটি পদ্ধতি তৈরি করার জন্য আমি নিজেই এটি করেছি । এটি এখনও খুব কমই সঠিকভাবে করা উচিত।
ক্রেগ পি। মোটলিন

6
এটি সাধারণভাবে ভাল পরামর্শ, তবে এটি প্রশ্নের উত্তর দেয় না।
নবীন

1
নেট নেটওয়ার্কের INotifyPropertyChangedইন্টারফেসটি প্রয়োগ করার সময় কলার সম্পর্কে তথ্য প্রাপ্তির সঠিক নকশার সিদ্ধান্ত কখন হতে পারে তার একটি দৃ concrete় উদাহরণ । যদিও এই নির্দিষ্ট উদাহরণটি জাভাতে নেই, ক্ষেত্রগুলি / গেটারদের প্রতিফলনের জন্য স্ট্রিং হিসাবে মডেল করার চেষ্টা করার সময় একই সমস্যাটি উদ্ভাসিত হতে পারে।
ক্রিস কেরিকস

30

জাভা 9 - জেপি 259: স্ট্যাক-ওয়াকিং এপিআই

জেপ 259 স্ট্যাক ওয়াকিংয়ের জন্য একটি কার্যকর স্ট্যান্ডার্ড এপিআই সরবরাহ করে যা স্ট্যাক ট্রেসগুলির তথ্যগুলিকে সহজে ফিল্টারিং এবং অলস অ্যাক্সেসের অনুমতি দেয়। স্ট্যাক-ওয়াকিং এপিআইয়ের আগে, স্ট্যাক ফ্রেমগুলিতে অ্যাক্সেসের সাধারণ উপায়গুলি ছিল:

Throwable::getStackTraceএবং অবজেক্টগুলির Thread::getStackTraceএকটি অ্যারে ফিরিয়ে দিন StackTraceElement, যা প্রতিটি স্ট্যাক-ট্রেস উপাদানটির শ্রেণীর নাম এবং পদ্ধতির নাম ধারণ করে।

SecurityManager::getClassContextএকটি সুরক্ষিত পদ্ধতি, যা একটি SecurityManagerসাবক্লাসকে শ্রেণি প্রসঙ্গে অ্যাক্সেস করতে দেয়।

JDK- অভ্যন্তরীণ sun.reflect.Reflection::getCallerClassপদ্ধতি যা আপনাকে আর ব্যবহার করা উচিত নয়

এই API গুলি ব্যবহার করা সাধারণত অদক্ষ হয়:

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

তাত্ক্ষণিক কলারের ক্লাসটি সন্ধান করতে প্রথমে একটি StackWalker:

StackWalker walker = StackWalker
                           .getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE);

তারপরে হয় ফোন করুন getCallerClass():

Class<?> callerClass = walker.getCallerClass();

বা s এবং পেতে প্রথম পূর্ববর্তী :walkStackFrameStackFrame

walker.walk(frames -> frames
      .map(StackWalker.StackFrame::getDeclaringClass)
      .skip(1)
      .findFirst());

15

অনেলাইনার :

Thread.currentThread().getStackTrace()[2].getMethodName()

নোট করুন যে আপনার 2 টি 1 দিয়ে প্রতিস্থাপন করতে হতে পারে।


10

এই পদ্ধতিটি একই জিনিসটি করে তবে কিছুটা আরও সহজ এবং সম্ভবত আরও কিছু পারফরম্যান্ট এবং আপনি যদি প্রতিচ্ছবিটি ব্যবহার করছেন তবে এটি স্বয়ংক্রিয়ভাবে এই ফ্রেমগুলি এড়িয়ে চলে। একমাত্র বিষয়টি হ'ল এটি অ-সান জেভিএমগুলিতে উপস্থিত নাও হতে পারে, যদিও এটি জেআরকিট ১.৪ -> ১.6 এর রানটাইম ক্লাসে অন্তর্ভুক্ত রয়েছে। (পয়েন্টটি হ'ল এটি কোনও পাবলিক ক্লাস নয়)।

sun.reflect.Reflection

    /** Returns the class of the method <code>realFramesToSkip</code>
        frames up the stack (zero-based), ignoring frames associated
        with java.lang.reflect.Method.invoke() and its implementation.
        The first frame is that associated with this method, so
        <code>getCallerClass(0)</code> returns the Class object for
        sun.reflect.Reflection. Frames associated with
        java.lang.reflect.Method.invoke() and its implementation are
        completely ignored and do not count toward the number of "real"
        frames skipped. */
    public static native Class getCallerClass(int realFramesToSkip);

এ পর্যন্ত কি যত realFramesToSkipমান হওয়া উচিত, সূর্য 1.5 এবং এর 1.6 VM- র সংস্করণ java.lang.System, একটি প্যাকেজ সংরক্ষিত পদ্ধতি getCallerClass () যা কল বলা হয় sun.reflect.Reflection.getCallerClass(3), কিন্তু আমার সাহায্যকারী ইউটিলিটি ক্লাসে 4 ব্যবহৃত যেহেতু আছে সাহায্যকারী ক্লাসের যোগ ফ্রেম আবাহন।


16
জেভিএম বাস্তবায়ন ক্লাস ব্যবহার সত্যিই খারাপ ধারণা।
লরেন্স ডল

7
উল্লেখযোগ্য। আমি উল্লেখ করেছি যে এটি কোনও পাবলিক ক্লাস নয়, এবং জাভা.এলং-তে সুরক্ষিত পদ্ধতিটি getCallerClass () পাওয়া যায়। ।
নিকোলাস

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

8
এছাড়াও, অনুরূপ যুক্তি দিয়ে আপনি এও বিতর্ক করতে পারেন যে আপনি যে কোনও সময় হাইবারনেট-নির্দিষ্ট বৈশিষ্ট্য ব্যবহার করেন যা জেপিএ উপযুক্ত নয়, এটি সর্বদা একটি " সত্যই খারাপ ধারণা"। বা যদি আপনি ওরাকল-নির্দিষ্ট বৈশিষ্ট্যগুলি ব্যবহার করতে যা যা অন্যান্য ডেটাবেজে পাওয়া যায় না, এটি " সত্যই খারাপ ধারণা"। নিশ্চিত যে এটি একটি নিরাপদ মানসিকতা এবং নির্দিষ্ট ব্যবহারের জন্য অবশ্যই ভাল পরামর্শ, তবে স্বয়ংক্রিয়ভাবে দরকারী সরঞ্জামগুলি ফেলে দেওয়া কেবল কারণ এটি কোনও সফ্টওয়্যার কনফিগারেশনের সাথে কাজ করবে না যে আপনি, আহ .. কিছু না ব্যবহার করছেন না ? এটি কিছুটা জটিল এবং কিছুটা মূর্খ।

5
বিক্রেতার নির্দিষ্ট শ্রেণীর অরক্ষিত ব্যবহার সমস্যাগুলির উচ্চতর সম্ভাবনা উপস্থাপন করবে, তবে যদি প্রশ্নে থাকা বর্গ উপস্থিত না থাকে (বা কোনও কারণে নিষিদ্ধ) তবে কারও পক্ষে গ্রেফতার হয়ে অবনমিত হওয়ার একটি উপায় নির্ধারণ করা উচিত। ফ্ল্যাট-আউট কোনও নির্দিষ্ট বিক্রেতার নির্দিষ্ট ক্লাস ব্যবহার অস্বীকার করার নীতিটি আমার মতে, কিছুটা নির্বোধ। আপনি উত্পাদনে ব্যবহার করেন এমন কয়েকটি লাইব্রেরির উত্স কোডের আশেপাশে ঝাঁকুনি দেখুন এবং সেগুলির মধ্যে এটি কোনও কাজ করে কিনা। (sun.misc.Unsafe সম্ভবত?)
নিকোলাস

7
     /**
       * Get the method name for a depth in call stack. <br />
       * Utility function
       * @param depth depth in the call stack (0 means current method, 1 means call method, ...)
       * @return method name
       */
      public static String getMethodName(final int depth)
      {
        final StackTraceElement[] ste = new Throwable().getStackTrace();

        //System. out.println(ste[ste.length-depth].getClassName()+"#"+ste[ste.length-depth].getMethodName());
        return ste[ste.length - depth].getMethodName();
      }

উদাহরণস্বরূপ, আপনি যদি ডিবাগ উদ্দেশ্যে কলিং পদ্ধতি লাইনটি পেতে চেষ্টা করেন তবে আপনাকে সেই স্ট্যাটিক পদ্ধতিগুলির কোডটি ইউটিলিটি ক্লাসটি
পেরিয়ে যেতে হবে : (পুরাতন জাভা ১.৪ কোড, কেবল একটি সম্ভাব্য স্ট্যাকট্রেস এলিমেন্টের ব্যবহার চিত্রিত করার জন্য)

        /**
          * Returns the first "[class#method(line)]: " of the first class not equal to "StackTraceUtils". <br />
          * From the Stack Trace.
          * @return "[class#method(line)]: " (never empty, first class past StackTraceUtils)
          */
        public static String getClassMethodLine()
        {
            return getClassMethodLine(null);
        }

        /**
          * Returns the first "[class#method(line)]: " of the first class not equal to "StackTraceUtils" and aclass. <br />
          * Allows to get past a certain class.
          * @param aclass class to get pass in the stack trace. If null, only try to get past StackTraceUtils. 
          * @return "[class#method(line)]: " (never empty, because if aclass is not found, returns first class past StackTraceUtils)
          */
        public static String getClassMethodLine(final Class aclass)
        {
            final StackTraceElement st = getCallingStackTraceElement(aclass);
            final String amsg = "[" + st.getClassName() + "#" + st.getMethodName() + "(" + st.getLineNumber()
            +")] <" + Thread.currentThread().getName() + ">: ";
            return amsg;
        }

     /**
       * Returns the first stack trace element of the first class not equal to "StackTraceUtils" or "LogUtils" and aClass. <br />
       * Stored in array of the callstack. <br />
       * Allows to get past a certain class.
       * @param aclass class to get pass in the stack trace. If null, only try to get past StackTraceUtils. 
       * @return stackTraceElement (never null, because if aClass is not found, returns first class past StackTraceUtils)
       * @throws AssertionFailedException if resulting statckTrace is null (RuntimeException)
       */
      public static StackTraceElement getCallingStackTraceElement(final Class aclass)
      {
        final Throwable           t         = new Throwable();
        final StackTraceElement[] ste       = t.getStackTrace();
        int index = 1;
        final int limit = ste.length;
        StackTraceElement   st        = ste[index];
        String              className = st.getClassName();
        boolean aclassfound = false;
        if(aclass == null)
        {
            aclassfound = true;
        }
        StackTraceElement   resst = null;
        while(index < limit)
        {
            if(shouldExamine(className, aclass) == true)
            {
                if(resst == null)
                {
                    resst = st;
                }
                if(aclassfound == true)
                {
                    final StackTraceElement ast = onClassfound(aclass, className, st);
                    if(ast != null)
                    {
                        resst = ast;
                        break;
                    }
                }
                else
                {
                    if(aclass != null && aclass.getName().equals(className) == true)
                    {
                        aclassfound = true;
                    }
                }
            }
            index = index + 1;
            st        = ste[index];
            className = st.getClassName();
        }
        if(resst == null) 
        {
            //Assert.isNotNull(resst, "stack trace should null"); //NO OTHERWISE circular dependencies 
            throw new AssertionFailedException(StackTraceUtils.getClassMethodLine() + " null argument:" + "stack trace should null"); //$NON-NLS-1$
        }
        return resst;
      }

      static private boolean shouldExamine(String className, Class aclass)
      {
          final boolean res = StackTraceUtils.class.getName().equals(className) == false && (className.endsWith("LogUtils"
            ) == false || (aclass !=null && aclass.getName().endsWith("LogUtils")));
          return res;
      }

      static private StackTraceElement onClassfound(Class aclass, String className, StackTraceElement st)
      {
          StackTraceElement   resst = null;
          if(aclass != null && aclass.getName().equals(className) == false)
          {
              resst = st;
          }
          if(aclass == null)
          {
              resst = st;
          }
          return resst;
      }

আমার জাভা 1.4 এর সাথে কাজ করে এমন কিছু দরকার ছিল এবং এই উত্তরটি খুব সহায়ক ছিল! ধন্যবাদ!
আরজিও

6

আমি এটি আগেও করেছি। আপনি কেবল একটি নতুন ব্যতিক্রম তৈরি করতে পারেন এবং স্ট্যাকের ট্রেসটি এটি ছুঁড়ে না ফেলে ধরে ফেলতে পারেন, তারপরে স্ট্যাকের ট্রেস পরীক্ষা করতে পারেন। অন্য উত্তরটি যদিও বলেছে যে এটি অত্যন্ত ব্যয়বহুল - একটি শক্ত লুপে এটি করবেন না।

আমি আগে এমন কোনও অ্যাপ্লিকেশনটিতে লগিং ইউটিলিটির জন্য করেছি যেখানে পারফরম্যান্স খুব বেশি গুরুত্ব দেয় না (পারফরম্যান্স খুব কমই খুব বেশি গুরুত্ব দেয়, আসলে - যতক্ষণ আপনি কোনও ক্রয়ের যেমন ফলাফলটি দ্রুত প্রদর্শন করেন ততক্ষণ))

আপনি স্ট্যাক ট্রেস পাওয়ার আগে এটি ছিল, ব্যতিক্রমগুলি কেবলমাত্র .প্রিন্টস্ট্যাকট্রেস () পেয়েছিলেন তাই আমার নিজের তৈরির একটি স্ট্রিমে সিস্টেম.আউটআউটকে পুনঃনির্দেশ করতে হয়েছিল, তারপরে (নতুন ব্যতিক্রম ()) প্রিন্টস্ট্যাকট্রেস (); পুনঃনির্দেশ System.out ফিরে এবং প্রবাহটি বিশ্লেষণ করুন। মজার জিনিস.


Cool; আপনি এটি নিক্ষেপ করতে হবে না?
krosenvold

না, কমপক্ষে আমি এটি এটি মনে রাখব, আমি এটি কয়েক বছরেই করিনি, তবে আমি নিশ্চিত যে একটি ব্যতিক্রম নতুন করে নেওয়া কেবল একটি অবজেক্ট তৈরি করে, এবং ব্যতিক্রম নিক্ষেপ করা এটিকে পাস ছাড়া কিছু করে না sure এটি ধরার () ধারাটিতে।
বিল কে

ঝরঝরে। আমি একটি সত্য ব্যতিক্রম অনুকরণ করতে এটি নিক্ষেপ উপর ঝোঁক ছিল।
সতীশ

না, জাভা 5 সাল থেকে স্ট্যাকট্রেস এলিমেন্টের অ্যারে হিসাবে বর্তমান স্ট্যাকটি পেতে থ্রেডে একটি পদ্ধতি রয়েছে; এটি এখনও সস্তা নয়, তবে পুরানো ব্যতিক্রম-পার্সিং সমাধানের চেয়ে সস্তা।
লরেন্স ডল

@ সফটওয়্যার বানর যদিও আমি নিশ্চিত যে এটি আরও উপযুক্ত, তবে আপনাকে কী বলে যে এটি সস্তা? আমি ধরে নিয়েছি একই প্রক্রিয়াটি ব্যবহার করা হবে, এবং যদি না হয়, যখন এটি একই জিনিসটি করে তখন একটি ধীর করে কেন?
বিল কে

1
private void parseExceptionContents(
      final Exception exception,
      final OutputStream out)
   {
      final StackTraceElement[] stackTrace = exception.getStackTrace();
      int index = 0;
      for (StackTraceElement element : stackTrace)
      {
         final String exceptionMsg =
              "Exception thrown from " + element.getMethodName()
            + " in class " + element.getClassName() + " [on line number "
            + element.getLineNumber() + " of file " + element.getFileName() + "]";
         try
         {
            out.write((headerLine + newLine).getBytes());
            out.write((headerTitlePortion + index++ + newLine).getBytes() );
            out.write((headerLine + newLine).getBytes());
            out.write((exceptionMsg + newLine + newLine).getBytes());
            out.write(
               ("Exception.toString: " + element.toString() + newLine).getBytes());
         }
         catch (IOException ioEx)
         {
            System.err.println(
                 "IOException encountered while trying to write "
               + "StackTraceElement data to provided OutputStream.\n"
               + ioEx.getMessage() );
         }
      }
   }

0

এই বিষয়টিতে প্রদর্শিত ইঙ্গিতগুলির ভিত্তিতে আমি তৈরি কোডের একটি অংশ এখানে। আশা করি এটা সাহায্য করবে.

(এই কোডটি উন্নত করতে কোনও পরামর্শ দিতে বিনা দ্বিধায় দয়া করে আমাকে বলুন)

কাউন্টার:

public class InstanceCount{
    private static Map<Integer, CounterInstanceLog> instanceMap = new HashMap<Integer, CounterInstanceLog>();
private CounterInstanceLog counterInstanceLog;


    public void count() {
        counterInstanceLog= new counterInstanceLog();
    if(counterInstanceLog.getIdHashCode() != 0){
    try {
        if (instanceMap .containsKey(counterInstanceLog.getIdHashCode())) {
         counterInstanceLog= instanceMap .get(counterInstanceLog.getIdHashCode());
    }

    counterInstanceLog.incrementCounter();

            instanceMap .put(counterInstanceLog.getIdHashCode(), counterInstanceLog);
    }

    (...)
}

এবং অবজেক্ট:

public class CounterInstanceLog{
    private int idHashCode;
    private StackTraceElement[] arrayStackTraceElements;
    private int instanceCount;
    private String callerClassName;

    private StackTraceElement getProjectClasses(int depth) {
      if(depth< 10){
        getCallerClassName(sun.reflect.Reflection.getCallerClass(depth).getName());
        if(getCallerClassName().startsWith("com.yourproject.model")){
            setStackTraceElements(Thread.currentThread().getStackTrace());
            setIdHashCode();
        return arrayStackTraceElements[depth];
        }
        //+2 because one new item are added to the stackflow
        return getProjectClasses(profundidade+2);           
      }else{
        return null;
      }
    }

    private void setIdHashCode() {
        if(getNomeClasse() != null){
            this.idHashCode = (getCallerClassName()).hashCode();
        }
    }

    public void incrementaContador() {
    this.instanceCount++;
}

    //getters and setters

    (...)



}

0
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintWriter;

class DBConnection {
    String createdBy = null;

    DBConnection(Throwable whoCreatedMe) {
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        PrintWriter pw = new PrintWriter(os);
        whoCreatedMe.printStackTrace(pw);
        try {
            createdBy = os.toString();
            pw.close();
            os.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

public class ThrowableTest {

    public static void main(String[] args) {

        Throwable createdBy = new Throwable(
                "Connection created from DBConnectionManager");
        DBConnection conn = new DBConnection(createdBy);
        System.out.println(conn.createdBy);
    }
}

অথবা

public static interface ICallback<T> { T doOperation(); }


public class TestCallerOfMethod {

    public static <T> T callTwo(final ICallback<T> c){
        // Pass the object created at callee to the caller
        // From the passed object we can get; what is the callee name like below.
        System.out.println(c.getClass().getEnclosingMethod().getName());
        return c.doOperation();
    }

    public static boolean callOne(){
        ICallback callBackInstance = new ICallback(Boolean){
            @Override
            public Boolean doOperation() 
            {
                return true;
            }
        };
        return callTwo(callBackInstance);
    }

    public static void main(String[] args) {
         callOne();
    }
}

0

এই পদ্ধতিটি ব্যবহার করুন: -

 StackTraceElement[] stacktrace = Thread.currentThread().getStackTrace();
 stackTraceElement e = stacktrace[2];//maybe this number needs to be corrected
 System.out.println(e.getMethodName());

পদ্ধতির উদাহরণ কোডের কলার এখানে রয়েছে: -

public class TestString {

    public static void main(String[] args) {
        TestString testString = new TestString();
        testString.doit1();
        testString.doit2();
        testString.doit3();
        testString.doit4();
    }

    public void doit() {
        StackTraceElement[] stacktrace = Thread.currentThread().getStackTrace();
        StackTraceElement e = stacktrace[2];//maybe this number needs to be corrected
        System.out.println(e.getMethodName());
    }

    public void doit1() {
        doit();
    }

    public void doit2() {
        doit();
    }

    public void doit3() {
        doit();
    }

    public void doit4() {
        doit();
    }
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.