Мне нужно найти вызывающего метода. Возможно ли использовать Stacktrace или отражение?
java
stack-trace
Sathish
источник
источник
DontNameYourMethodFooException
вызывается метод, называемый foo.Ответы:
Согласно Javadocs:
StackTraceElement
ИмеетgetClassName()
,getFileName()
,getLineNumber()
иgetMethodName()
.Вам придется поэкспериментировать, чтобы определить, какой индекс вы хотите (вероятно,
stackTraceElements[1]
или[2]
).источник
Альтернативное решение можно найти в комментарии к этому запросу на улучшение . Он использует
getClassContext()
метод customSecurityManager
и кажется быстрее, чем метод трассировки стека.Следующая программа проверяет скорость различных предложенных методов (наиболее интересный бит находится во внутреннем классе
SecurityManagerMethod
):Пример вывода с моего 2,4 ГГц Intel Core 2 Duo MacBook под управлением Java 1.6.0_17:
Метод внутреннего отражения намного быстрее, чем другие. Получение трассировки стека от вновь созданного
Throwable
быстрее, чем получение от текущегоThread
. И среди не внутренних способов поиска класса вызывающего абонента обычайSecurityManager
выглядит самым быстрым.Обновить
Как указывает lyomi в этом комментарии, этот
sun.reflect.Reflection.getCallerClass()
метод был отключен по умолчанию в Java 7 update 40 и полностью удален в Java 8. Подробнее об этом читайте в этой статье в базе данных ошибок Java .Обновление 2
Как обнаружил zammbi , Oracle был вынужден отказаться от изменений, которые удалили
sun.reflect.Reflection.getCallerClass()
. Это все еще доступно в Java 8 (но это устарело).Обновление 3
3 года спустя: обновление по времени с текущей JVM.
источник
Похоже, вы пытаетесь избежать передачи ссылки
this
на метод. Передачаthis
намного лучше, чем поиск вызывающего по текущей трассировке стека. Рефакторинг к более оригинальному дизайну еще лучше. Вам не нужно знать звонящего. Передайте объект обратного вызова при необходимости.источник
LoggerFactory.getLogger(MyClass.class)
где мне не нужно было проходить в литерале класса. Это все еще редко правильная вещь.INotifyPropertyChanged
интерфейса .NET . Хотя этот конкретный пример отсутствует в Java, та же проблема может проявиться при попытке смоделировать поля / получатели как строки для Reflection.Java 9 - JEP 259: API стека
JEP 259 предоставляет эффективный стандартный API для обхода стека, который позволяет легко фильтровать и легко получать доступ к информации в следах стека. До использования Stack-Walking API распространенными способами доступа к фреймам стека были:
Использование этих API обычно неэффективно:
Чтобы найти класс непосредственного абонента, сначала получите
StackWalker
:Затем либо позвоните
getCallerClass()
:или
walk
вStackFrame
s и получить первый предшествующийStackFrame
:источник
Oneliner :
Обратите внимание, что вам может понадобиться заменить 2 на 1.
источник
Этот метод делает то же самое, но немного проще и, возможно, немного более производительно, и, если вы используете отражение, он автоматически пропускает эти кадры. Единственная проблема заключается в том, что он может отсутствовать в JVM, отличных от Sun, хотя он включен в классы выполнения JRockit 1.4 -> 1.6. (Дело в том, что это не публичный класс).
Насколько это
realFramesToSkip
должно быть, в версиях Sun 1.5 и VMjava.lang.System
, есть метод с защитой пакетов, называемый getCallerClass (), который вызываетsun.reflect.Reflection.getCallerClass(3)
, но в своем вспомогательном служебном классе я использовал 4, поскольку есть добавленный фрейм вспомогательного класса. призывание.источник
Например, если вы пытаетесь получить строку вызывающего метода для целей отладки, вам нужно пройти класс Utility, в котором вы
кодируете эти статические методы: (старый код java1.4, просто чтобы проиллюстрировать потенциальное использование StackTraceElement)
источник
Я делал это раньше. Вы можете просто создать новое исключение и получить трассировку стека, не выбрасывая его, а затем изучить трассировку стека. Как говорится в другом ответе, это чрезвычайно дорого - не делайте это в узком кругу.
Я делал это раньше для утилиты журналирования в приложении, где производительность не имела большого значения (вообще-то, производительность вообще не имеет большого значения - если вы отображаете результат для действия, например, быстрого нажатия кнопки).
Это было до того, как вы смогли получить трассировку стека, исключения имели только .printStackTrace (), поэтому мне пришлось перенаправить System.out в поток моего собственного создания, затем (new Exception ()). PrintStackTrace (); Перенаправьте System.out обратно и проанализируйте поток. Прикольные вещи.
источник
источник
Вот часть кода, который я сделал на основе подсказок, показанных в этой теме. Надеюсь, поможет.
(Не стесняйтесь делать какие-либо предложения по улучшению этого кода, пожалуйста, сообщите мне)
Счетчик:
И объект:
источник
ИЛИ
источник
используйте этот метод: -
Вызывающий метод примера кода здесь: -
источник