Налагодження Java додатки, яку не можна зупинити. Ловимо екзотику виконання найдоступнішими средсвами - BTrace підхід

    
 Java додатки — значить в сучасному Java світі можливість зустріти таке відсотків на 90%, а то й більше (розглядаємо найпоширеніші оточення, HotSpot based JVM версії від 1.6)
 яку не можна зупинити — додаток працює, і перезапускати його з тих чи інших причин категорично не можна
 екзотика — щось таке отаке, що не кожен день на думку спаде спіймати (певна послідовність виклику методів, дивовижні комбінації значень параметрів, ...)
 доступними средсвами — безкоштовно, працездатне, ефективно, легко, просто і т.д і т.п. У даній статті розглянуто чудовий інструмент BTrace kenai.com / projects / btrace
 
І само собою в код Java програми заздалегідь нічого спеціально не додано стосовно засобів дебагом…
 
 
 
Дана стаття по суті є продовженням поста «Налагодження Java додатки, коли воно зовсім не чекає — ласкаво просимо в InTrace підхід» habrahabr.ru/post/219661 , в якому було показано як вклинитися у вже запущене застосування і зібрати досить докладний трейс виконання. Що є дуже корисне майстерність, але в реальному житті, іноді, бувають випадки, коли проскакує незрозуміла поведінка з імовірністю 1 на 1 000, а то й гірше, і спробуй паді це знайди в тоннах Трейсі.
Тому беремо для прикладу простеньку програму (файл excitement / Coin.java) і збиратимемо «екзотику» на льоту.
 
 
package excitement;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Random;

public class Coin {
  public void head() {
  }

  public void tail() {
  }

  public static void main(String... args) throws Exception {
    System.out.println("Нажмите любой Enter для продолжения...");
    new BufferedReader(new InputStreamReader(System.in)).readLine();

    Random rand = new Random();

    for (int count = 0; count < 1000; ++count) {
      if (rand.nextInt(2) > 0) {
        new Coin().head();
      } else {
        new Coin().tail();
      }
    }
    System.out.println("Вот и всё!");
  }

}


 
Скомпілюємо
 
javac excitement/Coin.java

 
І запустимо
 
javac excitement.Coin

 
Адже простіше нікуди, правда? )
 
За екзотику я візьму хвилююче питання: «Скільки ж разів поспіль максимально випадуть орел і решка, ну а також взагалі скільки разів вони просто випадуть?» Такий собі тест rand.nextInt (2). Які прогнози? Ставки приймаються…
 
Отримати відповідь допоможе дуже відомий і, до до всього іншого, просто чудовий інструмент BTrace kenai.com / projects / btrace , неодноразово згадуваний на Хабре в коментах, але на жаль жодного разу досі не описаним в постах.
 
Для його запуску варто розглянути пару способів:
1) любителям командного рядка — консольна утиліта викачувана з kenai.com/projects/btrace/downloads/directory/releases/release-1.2.4 (остання доступна версія)
і запускається як
 
btrace <PID> TracingScript.java

де
PID — це ідентифікатор процесу (одержуваний, наприклад, через jps)
TracingScript.java — трасуючий скрипт, з яким більш щільне знайомство буде трохи далі
 
2) любителям віконець пропонується використовувати плагін в VisualVM visualvm.java.net / download.html . Для чого заходимо в Tools-> Plugins-> Available Plugins кликаем BTrace Workbench і тиснемо «Install», уважно читаємо ліцензію (хоча хто їх читає), гаразд, так і бути, без найменших вагань погоджуємося в цьому і наступних вікнах на всі при все. І тепер, після успішної установки, в контекстному меню цікавить процесу, в VisualVM з'явився новий пункт «Trace Application ...»
 
 
 
BTrace робить свою роботу покладаючись на алгоритм описаний в дуже Java подібному скрипті (також можна використовувати D-scriptи). Дуже подібному — оскільки це як би і сама що ні наїсти Java, але все ж через те, що BTrace не змінює виконання трассируемого програми (я маю на увазі все ж намагається не модифікувати її поведінку, тільки отримувати інформацію про виконання максимально дотримуючись формату « read-only »), доводитися забути про безліч речей Джави (починаючи зі створення нових об'єктів і закінчуючи ще багато чим, см. kenai.com / projects / btrace / pages / UserGuide BTrace Restrictions) і використовувати кошти надаються безпосередньо BTrace.
 
А тепер скрипт (файл TracingScript.java)
 
 
import com.sun.btrace.annotations.*;
import static com.sun.btrace.BTraceUtils.*;

@BTrace // скриптом выступает джава класс
public class TracingScript {
@Property // возможно смотреть значения "на лету" через MBean JMX (jconsole, VisualVM, ...)
private static long tailCount;
@Property(name="Total head count is") // другое имя для JMX
private static long headCount;
@Property
private static long maxHeadSequence = 1;
@Property
private static long maxTailSequence = 1;
@Property
private static long sequence = 1;
@Property
private static long prevId = -1;

@OnMethod(clazz = "excitement.Coin",  // вклиниваемся в метод в пакете  excitement класса Coin
         method = "head", // c именем head
         location = @Location(Kind.RETURN)) // при возврате из него
 public static void onHead() {
    ++headCount;
    sequence = prevId == 0 ? sequence + 1 : 1;
    if (sequence > maxHeadSequence) maxHeadSequence = sequence;
    prevId = 0;
 }

@OnMethod(clazz = "excitement.Coin", 
         method = "tail", 
         location = @Location(Kind.RETURN))
 public static void onTail() {
    ++tailCount;
    sequence = prevId == 1 ? sequence + 1 : 1;
    if (sequence > maxTailSequence) maxTailSequence = sequence;
    prevId = 1;
 }

@OnExit // вызывается при завершении программы
public static void onexit(int code) {
        println(strcat("total heads:", str(headCount))); // из-за ограничения на создание объектов  наблюдаются свои примочки по работе со строками
        println(strcat("total tails:", str(tailCount)));
        println(strcat("max tail sequence:", str(maxTailSequence)));
        println(strcat("max head sequence:", str(maxHeadSequence)));
    }
}

 
Зрештою, запускаємо цей скрипт, тиснемо «Enter» в очікує кидання монет програмі і отримуємо (у кого як, а у мене вийшло так):
 
 
total heads:531

 
total tails:469

 
max tail sequence:9

 
max head sequence:8

 
В цілому орел і решка трапилося випадали по 8 і 9 разів поспіль (хоча у мене за кілька запусків бувало й 10-11 разів). Бажаючим пропонується самостійно перевірити наскільки отримане збігається з результатами формул теорії ймовірностей (щоб не заїхати тут у складну тему щодо способів генерації таких простих випадкових чисел).
 
Підводячи підсумки:
BTrace неабияк потужний інструмент, що дозволяє на льоту трассіровать вельми і вельми діковенние особливості виконання. У даній статті порушено лише вершина айсберга його шикарних можливостей (при бажанні хоч бери та пиши книгу), матеріал наводиться з метою викласти самі ази і як можна більш зацікавити. Кого зачепило, дивіться більш детально тут kenai.com / projects / btrace / pages / UserGuide , перш за все, зверніть увагу на кількість анотацій і довгий список дуже-дуже життєво корисних прикладів. Але все ж не забувайте — все відбувається на свій страх і ризик, бо застосовувана BTracе для досягнення мети (вклинювання) трансформація Java класів, завжди може зіграти злий жарт.
 
І наостанок, про монети (фізика та й тільки) — часто монета не ідеально збалансована (зазвичай орел трохи важче решки), так що підкинути монету і отримати 50/50 в реальному житті не вдасться. Будьте пильні, беріть сторону монети безпосередньо розумом.
Та прибуде з вами удача)
 
Дякую за увагу!
    
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.