| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > Java: Общие вопросы > Как узнать из какого метода позвался |
| Автор: Royan 18.5.2005, 13:42 | ||
| Всем привет, Банальный вопрос, имеем
Такой вот вопрос. Сразу скажу решение, которое не хочется применять - это кинуть в b() exception и проанализировать стек, но это грубо, может можно более элегантно? |
| Автор: batigoal 18.5.2005, 13:45 |
| Мне кажется, в данном случае не кривого решения и не может быть. Лучше всего переделать код, чтобы он передавал в метод b ссылку на себя this. Может, через рефлексию как-нибудь можно? |
| Автор: 3,14 18.5.2005, 16:03 |
| Можно конечно воспользоваться Thread.dumpStack(), но лучше сделать так как советует Lamer George |
| Автор: AntonSaburov 18.5.2005, 16:18 | ||
Я делал так - просто кидал эксепшн. Что-то вроде такого
|
| Автор: batigoal 18.5.2005, 16:29 |
| AntonSaburov Но ведь это не очень хорошо с точки зрения рефакторинга - имя метода поменяется, и строку придется парсить по-другому... |
| Автор: AntonSaburov 18.5.2005, 16:37 | ||
Зачем по-другому - формат ведь всегда стандартный. Ты просто печатаешь стэк. Можно его вообще получать стандартно через StackTraceElement. Там просто имена методов получают отдельным методом.
|
| Автор: batigoal 18.5.2005, 16:42 |
| Ух ты, я и не знал про StackTraceElement. |
| Автор: Royan 18.5.2005, 19:08 |
| Признаюсь я смотрел в сторону этого класса, но угрожающий список параметров конструктора меня отпугнул, не знал, что его можно так просто использовать. Спасибо! |
| Автор: Stampede 18.5.2005, 19:17 | ||||
На самом деле кидать эксепшен необязательно - достаточно всего лишь создать объект типа Exception (ну или Throwable - кому как нравится). Чтобы узнать имя вызвавшего метода, получаем массив элементов StackTraceElement и ссылаемся на элемент с индексом 1 (нулевой элемент указывает на текущий метод).
Если быть точнее, то кидать эксепшен для целей получения стека не только необязательно, но и просто вредно - например, из соображений производительности, поскольку отработка цикла try-catch отъедает на порядок большее количество тактов. Кстати, до версии 1.4 получить стек можно было только в текстовом виде, и когда я писал свой асинхронный логгер в до- log4j эру, то мне приходилось полагаться на формат вывода printStackTrace() и парсить его до нужных элементов. Что вызывало у меня легкое чувство нервозности, потому как никогда не знаешь, какие улучшения в плане формата вывода могут взбрести в голову отцам-основателям в следующей верии Java. Но теперь жить стало лучше, жить стало веселей - спасибо партии за это! |
| Автор: Domestic Cat 18.5.2005, 19:21 | ||
На порядок - врядли, несколько гото и все. |
| Автор: Stampede 18.5.2005, 22:14 | ||||||
Не согласен. Несколько гото - это в случае нормального хода выполнения программы, когда исключений не происходит. В данном же примере предлагалось использовать try/catch на регулярной основе, для выуживания информации о вызывающем методе - и в этом случае мы можем говорить именно о серъезных потерях производительности. Причем потери эти совершенно неоправданные, на что я и указал в своем посте. Если говорить о конкретных цифрах, то вот я тут прилагаю отчет, сгенерированный маленьким тестовым апплетом, взятом из http://www.javaworld.com/javaworld/jw-04-1997/jw-04-optimize-p3.html:
Особое внимание прошу обратить на эту строчку: Throw and catch new Exception() 4175320 ps А вот что имеет сказать по данному поводу уважаемый мной Билл Веннерс:
Резюме: никогда не используйте try/catch как средство управления логикой нормального хода выполнения программы. |
| Автор: Domestic Cat 18.5.2005, 22:22 | ||
Дык это ведь не только логика ловли иксепшна, это и создание нового объекта что много времени занимает, а в данном случае он по-любому создается. Если по байткоду судить - ничего особо серьезного кетч не даст... Но конечно без него лучше. |
| Автор: Stampede 18.5.2005, 23:36 | ||||||||
Чудеса в решете какие-то. Взял сейчас, не поленился и написал маленький тест:
Получил вот такие результаты:
Расхождение оказалось совсем небольшим, так что я решил попробовать исключить из эксперимента время вывода на консоль, чтобы получить разницу, так сказать, в чистом виде. С этой целью я закомментировал в обоих методах строку с System.out.println() и запустил еще раз. Что бы вы думали?
То есть практически одинаковое время! Потом я еще маленько поэкспериментировал и пришел в выводу, что единственный и главный накладной расход при возникновении исключения - это создание собственно объекта Exception, а действиями по разруливанию try/catch можно действительно пренебречь. Этот факт не отменяет валидности моего (и не только моего) пойнта о том, что try/catch не должны использоваться для управления нормальной логикой, но вот применительно к случаю получения имени вызывающего метода - таки да, выбрасывание/ловля уже созданного исключения практически никакого дополнительного тормоза не привносит. Хотя как можно объяснить тот факт, что в самом первом тесте (с выводом на консоль) время все-таки отличалось в два раза?
Котъ, снимаю шляпу. Я по байткоду судить не умею, потому и чуть было не попал впросак. Забираю свои слова взад. Но Антону хочу сказать, что бросать/ловить исключение в его примере все равно не имело никакого смысла, даже если это и не повклекло за собой больших накладных расходов |
| Автор: Domestic Cat 19.5.2005, 00:00 | ||||||
Там ничего сложного нет, я вот тут писал: http://forum.vingrad.ru/index.php?showtopic=35748&st=0 А вот код для двух методов testNoThrow() и testThrow()
Тут JVM все так оптимизировала, что разницы практически нет |
| Автор: Stampede 19.5.2005, 22:34 |
| Кстати, на сайте моего любимого Билла Веннерса можно увидеть работу сего байткода (ну, в чуть-чуть измененном виде) в анимированном, так сказать, виде: http://www.artima.com/insidejvm/applets/PlayBall.html А на http://www.artima.com/java/index.html собраны ссылки на избранные главы из его книжки Inside The Java Virtual Machine, а также статьи, написанные им для колонки в Java World под названием Under The Hood (под капотом) - о различных аспектах внутреннего устройства JVM. Там же каталог апплетов, которые иллюстрируют работу JVM. Вообще, Билл Веннерс - это один из самых толковых чуваков в Java индустрии. Если раньше не видели - категорически рекомендую. Энджойте |
| Автор: batigoal 20.5.2005, 11:43 |
| Зачеким. |
| Автор: Royan 27.5.2005, 13:12 | ||
Если учесть что в винде погрешность таймера составляет 10ms, то эти цифры в равной степени могут свидетельствовать как о нуле так и о 20ms, так что... |
| Автор: Domestic Cat 27.5.2005, 19:08 |
| Там результаты на Маке и солярисе есть, а у них 1 мс. |