Stacktrace veya yansıma kullanarak bir yöntemin arayanını nasıl bulabilirim?


392

Bir yöntemin arayanını bulmam gerekiyor. Yığın izleme veya yansıma kullanmak mümkün müdür?


5
Sadece merak ediyorum, ama bunu neden yapmanız gerekecek?
Juliet

2
Notent olayı olan bir üst sınıf (MVC modeli) var ve sadece benim alt sınıf ayarlayıcıları bu yöntemi çağırır. i gereksiz bir argüman ile kodumu çöp istemiyorum. Üst sınıftaki yöntemin adı verilen ayarlayıcıyı çözmesine izin vermeyi tercih ederim.
Sathish

30
@Sathish Bu tasarımı yeniden düşünmeniz gerektiği gibi geliyor
krosenvold

7
@Juliet Büyük bir kod parçasını yeniden düzenlemenin bir parçası olarak, son zamanlarda birçok şey tarafından kullanılan bir yöntemi değiştirdim. Kod yeni yöntemi düzgün kullanıp kullanmadığını tespit etmek için belirli bir yolu var, bu yüzden bu durumlarda adı verilen sınıf ve satır numarasını yazdırıyordu. Kayıt dışında, böyle bir şey için gerçek bir amaç görmüyorum. Her ne kadar ben şimdi bir DontNameYourMethodFooExceptionçağıran yöntemi foo adlı bir atmak API's yazmak istiyorum .
Cruncher

5
Benim yöntem arayan arayan paha biçilmez bir hata ayıklama aracı bulmak mümkün: Bu bir web arama beni buraya getirdi. Metodum birden çok yerden çağrılıyorsa, doğru yerden doğru zamanda mı çağrılıyor? Hata ayıklama veya günlüğe kaydetmenin dışında, @Cruncher'ın belirttiği gibi, yararlılık muhtemelen en iyi şekilde sınırlıdır.
Ogre Psalm33

Yanıtlar:


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

Javadocs'a göre:

Dizinin son öğesi, dizideki en yeni yöntem çağırma olan yığının altını temsil eder.

Bir StackTraceElementsahiptir getClassName(), getFileName(), getLineNumber()ve getMethodName().

İstediğiniz dizini (muhtemelen stackTraceElements[1]veya [2]) belirlemek için denemeniz gerekir .


7
GetStackTrace () hala bir İstisna oluşturur, bu yüzden bu gerçekten daha hızlı değil - sadece daha uygun olduğunu unutmayın.
Michael Myers

42
Bu yöntemin size arayanı değil, yalnızca arayanın türünü vereceğini unutmayın . Metodunuzu çağıran nesneye referansınız olmayacaktır.
Joachim Sauer

3
Sadece bir yan not, ancak 1.5 JVM Thread.currentThread (). GetStackTrace () yeni bir Exception () oluşturmaktan çok daha yavaş görünüyor (yaklaşık 3 kat daha yavaş). Ancak daha önce belirtildiği gibi, zaten performans açısından kritik bir alanda böyle bir kod kullanmamalısınız. ;) 1.6 JVM sadece ~% 10 daha yavaş görünüyor ve Software Monkey'in dediği gibi, amacı "yeni İstisna" yolundan daha iyi ifade ediyor.
GaZ

21
@Eelco Thread.currentThread () ucuz. Thread.getStackTrace () pahalıdır, çünkü Throwable.fillInStackTrace () yönteminden farklı olarak, yöntemin incelediği aynı iş parçacığı tarafından çağrıldığına dair bir garanti yoktur, bu nedenle JVM bir "güvenli nokta" oluşturmak zorundadır - yığın ve yığını kilitler. Bu hata raporuna bakın: bugs.sun.com/bugdatabase/view_bug.do?bug_id=6375302
David Moles

7
@JoachimSauer yöntemi çağıran nesneye başvuru almak için bir yol biliyor musunuz?
jophde

216

Bu geliştirme talebinin yorumunda alternatif bir çözüm bulunabilir . getClassContext()Bir özel yöntemi kullanır ve SecurityManageryığın izleme yönteminden daha hızlı görünür.

Aşağıdaki program, önerilen farklı yöntemlerin hızını test eder (en ilginç bit iç sınıftır 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.");
  }
}

Java 1.6.0_17 çalıştıran 2.4 GHz Intel Core 2 Duo MacBook'umun çıktısına bir örnek:

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

Dahili Yansıma yöntemi diğerlerinden çok daha hızlıdır. Yeni oluşturulan bir yığın izini Throwablealmak, geçerli olandan almaktan daha hızlıdır Thread. Arayan sınıfını bulmanın içsel olmayan yolları arasında, gelenek SecurityManageren hızlı gibi görünüyor.

Güncelleme

As lyomi içinde işaret Bu yorumasun.reflect.Reflection.getCallerClass() yöntemi Java 7 güncelleme 40 varsayılan olarak devre ve daha bu konuda Java 8. okuyun tamamen kaldırılmıştır Java hata veritabanında bu konuda .

Güncelleme 2

Gibi zammbi bulmuştur Oracle edildi değişikliğin kapsamı dışında geri adım atmak zorunda kaldırıldı sun.reflect.Reflection.getCallerClass(). Java 8'de hala kullanılabilir (ancak kullanımdan kaldırılmıştır).

Güncelleme 3

3 yıl sonra: Güncel JVM ile zamanlama güncellemesi.

> 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
Evet, öyle görünüyor. Ancak, örnekte verdiğim zamanlamaların bir milyon çağrı için olduğunu unutmayın - bu yüzden bunu nasıl kullandığınıza bağlı olarak sorun olmayabilir.
Johan Kaving

1
Benim için yansımamın projemden kaldırılması 10 kat hız artışı ile sonuçlandı.
Kevin Parker

1
Evet, genel olarak yansıma yavaştır (bkz. Stackoverflow.com/questions/435553/java-reflection-performance ), ancak bu özel durumda dahili sun.reflect.Reflection sınıfı kullanmak en hızlısıdır.
Johan Kaving

1
Aslında buna gerek yok. Döndürülen className yazdırmak için yukarıdaki kodu değiştirerek doğrulayabilirsiniz (ve döngü sayısını 1'e düşürmenizi öneririm). Tüm yöntemlerin aynı className - TestGetCallerClassName döndürdüğünü göreceksiniz.
Johan Kaving

1
getCallerClass kullanımdan kaldırıldı ve 7u40'ta kaldırılacak .. sad :(
lyomi

36

thisYönteme başvurmaktan kaçınmaya çalıştığınız anlaşılıyor . Geçme this, arayanı mevcut yığın izinden bulmaktan çok daha iyidir. Daha fazla bir OO tasarımına yeniden bakmak daha da iyidir. Arayan kişiyi bilmenize gerek yoktur. Gerekirse bir geri arama nesnesi iletin.


6
++ Arayanın bilinmesi çok fazla bilgi. Gerekirse, bir arayüze geçebilirsiniz, ancak büyük bir yeniden düzenlemeye ihtiyaç duyulma olasılığı yüksektir. @satish kodunu göndermeli ve onunla biraz eğlenelim :)
Bill K

15
Bunu yapmak için geçerli nedenler var. Örneğin test sırasında faydalı bulduğum birkaç durum yaşadım.
Eelco

2
@chillenious biliyorum :) Kendimi LoggerFactory.getLogger(MyClass.class)yaptım sınıf değişmezi geçmek zorunda değildi gibi bir yöntem oluşturmak için . Hala nadiren yapılacak doğru şey.
Craig P. Motlin

6
Bu genel olarak iyi bir tavsiye, ancak soruya cevap vermiyor.
Navin

1
Arayan hakkında bilgi edinmenin DOĞRU tasarım kararının ne zaman olabileceğinin somut bir örneği, .NET INotifyPropertyChangedarabirimini uygularken . Bu belirli örnek Java'da olmasa da, aynı sorun alanları / alıcıları Yansıma dizeleri olarak modellemeye çalışırken kendini gösterebilir.
Chris Kerekes

31

Java 9 - JEP 259: Stack-Walking API'sı

JEP 259 , yığın izlemesindeki bilgilerin kolayca filtrelenmesini ve tembel olarak erişilmesini sağlayan yığın yürüyüşü için verimli bir standart API sağlar. Stack-Walking API'sinden önce yığın çerçevelerine erişmenin yaygın yolları şunlardı:

Throwable::getStackTraceve her yığın izleme öğesinin sınıf adını ve yöntem adını içeren bir nesne Thread::getStackTracedizisi döndürür StackTraceElement.

SecurityManager::getClassContextSecurityManageralt sınıfın sınıf içeriğine erişmesini sağlayan korumalı bir yöntemdir .

sun.reflect.Reflection::getCallerClassYine de kullanmamanız gereken JDK dahili yöntemi

Bu API'ları kullanmak genellikle yetersizdir:

Bu API'ler, VM'nin tüm yığının anlık görüntüsünü hevesle yakalamasını gerektirir ve yığının tamamını temsil eden bilgileri döndürür. Arayan kişi yalnızca yığındaki ilk birkaç kareyle ilgileniyorsa, tüm kareleri inceleme maliyetinden kaçınmanın bir yolu yoktur.

Hemen arayan kişinin sınıfını bulmak için önce aşağıdakileri elde edin StackWalker:

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

Sonra şunlardan birini arayın getCallerClass():

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

ya da S ve önceki birinci alır :walkStackFrameStackFrame

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

15

Oneliner :

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

2'yi 1 ile değiştirmeniz gerekebileceğini unutmayın.


10

Bu yöntem aynı şeyi yapar, ancak biraz daha basit ve muhtemelen biraz daha performanslı ve yansıma kullanıyorsanız, bu kareleri otomatik olarak atlar. Tek sorun, JRockit 1.4 -> 1.6 çalışma zamanı sınıflarına dahil olmasına rağmen, Sun olmayan JVM'lerde bulunmayabilir. (Mesele şu ki, bu bir kamu sınıfı değildir ).

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);

realFramesToSkipSun 1.5 ve 1.6 VM sürümlerinin değeri ne olursa olsun, java.lang.SystemgetCallerClass () adı verilen paket korumalı bir yöntem var sun.reflect.Reflection.getCallerClass(3), ancak çağıran yardımcı program sınıfımda yardımcı sınıfın ek çerçevesi olduğundan 4 kullandım çağırma.


16
JVM uygulama sınıflarının kullanımı gerçekten kötü bir fikirdir.
Lawrence Dol

7
Kayıt edilmiş. Ben bir ortak sınıf olmadığını ve java.lang.System korumalı yöntem getCallerClass () IBM, JRockit ve Sun dahil baktığım tüm 1.5+ VM'lerde mevcut olduğunu belirttiniz, ancak iddianız muhafazakar ses .
Nicholas

6
@Yazılım Maymun, her zamanki gibi, "hepsi bağlıdır". Hata ayıklamaya veya test günlüğüne yardımcı olmak için - özellikle üretim kodunda hiç bitmezse - veya dağıtım hedefi kesinlikle geliştiricinin PC'siyse, böyle bir şey yapmak muhtemelen iyi olacaktır. Böyle durumlarda bile hala aksini düşünen herkes: " gerçekten kötü bir fikir" akıl yürütmesini sadece kötü olduğunu söylemekten daha iyi açıklamanız gerekir ...

8
Ayrıca, benzer bir mantıkla, JPA uyumlu olmayan Hazırda Bekleme özel bir özellik kullandığınızda, bu her zaman " gerçekten kötü bir fikir" olduğunu iddia edebilirsiniz . Veya diğer veritabanlarında bulunmayan Oracle'a özgü özellikleri kullanacaksanız, bu gerçekten kötü bir fikirdir. Tabii bazı kullanımlar için daha güvenli bir zihniyet ve kesinlikle iyi bir öğüt, ama otomatik, ah .. sen şu bir yazılım yapılandırma ile değil iş olacak sırf atmadan yararlı araçlar hiç kullanmıyor ? Bu biraz fazla esnek ve biraz aptalca.

5
Satıcıya özgü sınıfların korumasız kullanımı daha yüksek bir sorun olasılığı ortaya koyacaktır, ancak söz konusu sınıf mevcut değilse (veya bir nedenden dolayı yasaklanmışsa) kişi kolayca bozulacak bir yol belirlemelidir. Herhangi bir satıcıya özel sınıf kullanmayı reddetme politikası, bence, biraz naif. Üretimde kullandığınız bazı kütüphanelerin kaynak kodunu araştırın ve bunlardan herhangi birinin bunu yapıp yapmadığını görün. (sun.misc.Unsafe belki?)
Nicholas

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();
      }

Örneğin, hata ayıklama amacıyla çağıran yöntem satırını almaya çalışırsanız, bu statik yöntemleri
kodladığınız Utility sınıfını geçmeniz gerekir: (eski java1.4 kodu, yalnızca potansiyel StackTraceElement kullanımını göstermek için)

        /**
          * 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;
      }

Java 1.4 ile çalışan bir şeye ihtiyacım vardı ve bu cevap çok yardımcı oldu! Teşekkür ederim!
RGO

6

Bunu daha önce yaptım. Yeni bir istisna oluşturabilir ve yığın izini atmadan yakalayabilir, ardından yığın izlemesini inceleyebilirsiniz. Diğer cevabın dediği gibi, son derece maliyetli - bunu sıkı bir döngüde yapmayın.

Daha önce performansın çok önemli olmadığı bir uygulamada bir günlük kayıt yardımcı programı için yaptım (Performansı nadiren çok önemli, aslında - sonucu hızlı bir şekilde tıklama gibi bir eyleme gösterdiğiniz sürece).

Yığın izini almadan önce, istisnaların sadece .printStackTrace () vardı, bu yüzden System.out'u kendi yaratımımın bir akışına yönlendirmek zorunda kaldım, sonra (yeni Exception ()). PrintStackTrace (); System.out'u yeniden yönlendirin ve akışı ayrıştırın. Eğlenceli şeyler.


Güzel; atmak zorunda değil misin?
krosenvold

Hayır, en azından bunu hatırlıyorum, birkaç yıldır yapmadım, ancak bir istisnanın yeni bir nesnesinin yaratıldığından eminim ve istisnayı atmak geçişte hiçbir şey yapmaz catch () maddesine.
Bill K

Temiz. Gerçek bir istisnayı simüle etmek için fırlatma eğilimindeydim.
Sathish

Hayır, Java 5'ten bu yana Thread'te geçerli yığını StackTraceElements dizisi olarak almak için bir yöntem vardır; hala ucuz değil, ancak eski istisna ayrıştırma çözümünden daha ucuz.
Lawrence Dol

@Yazılım Maymun Daha uygun olduğundan emin olmama rağmen, size daha ucuz olduğunu söyleyen nedir? Aynı mekanizmanın kullanılacağını varsayacağım ve eğer olmasa da, aynı şeyi yaptığında neden yavaşlayalım?
Bill K

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

İşte bu konuda gösterilen ipuçlarına dayanarak yaptığım kodun bir kısmı. Umarım yardımcı olur.

(Bu kodu geliştirmek için herhangi bir öneri yapmaktan çekinmeyin, lütfen bana bildirin)

Sayaç:

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);
    }

    (...)
}

Ve nesne:

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);
    }
}

VEYA

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

bu yöntemi kullanın: -

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

Yöntem örneğinin arayanı Kod burada: -

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();
    }
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.