Как следовать за источником значения в Java?

Взгляните на URLRewriter. Используемый это в производстве однажды без проблем. Но не полагайтесь на это как на единственную проверку качества:

http://www.codeplex.com/urlrewriter

(Это свободно и имеет Microsoft Public License)

Управляемый URL Fusion, Rewriter является мощным механизмом управления URL на основе Apache mod_rewrite расширение. Это разработано, с нуля для обеспечения всех функций Apache mod_rewrite к IIS 6.0 и IIS 7.0. Управляемый URL Fusion Rewriter работает с ASP.NET на Сервере информации об Интернете (IIS) Microsoft 6.0 и Моно Сервер XPS и полностью поддерживается, для всех языков, в IIS 7.0, включая ASP.NET и PHP. Управляемый URL Fusion Rewriter дает Вам свободу пойти вне стандартных схем URL и разработать Вашу собственную схему.

5
задан elifiner 25 October 2009 в 22:38
поделиться

10 ответов

Если вы используете сеттер и только сеттер для установки значения, вы можете добавить эти строки для отслеживания трассировки потока и стека:

public void setTimestamp(long value) {
  if(log.idDebugEnabled) {
    log.debug("Setting the value to " + value + ". Old value is " + this.timestamp);
    log.debug("Thread is " + Thread.currentThread().getName());
    log.debug("Stacktrace is", new Throwable()); // we could also iterate on Thread.currentThread().getStackTrace()
  }
  // check for bad value
  if(value & 0xffffffff00000000L == 0L) {
    log.warn("Danger Will Robinson", new IlegalValueException());
  }
  this.timestamp = value;
}

Также, перейдите по классу, содержащему поле, и убедитесь, что каждая ссылка на него выполняется через установщик (даже в частных / защищенных методах).

Изменить

Возможно, FindBugs может помочь с точки зрения статический анализ, я постараюсь найти точное правило позже.

6
ответ дан 18 December 2019 в 10:46
поделиться

Тот факт, что изменяются 32 бита длинной длины, а не все значение, убедительно свидетельствует о том, что это проблема потоковой передачи (два потока обновляют переменную одновременно). Поскольку java не гарантирует атомарный доступ к длинному значению, если два потока обновят его одновременно, это может привести к тому, что половина битов будет установлена ​​в одну сторону, а половина - в другую. Это означает, что лучший способ подойти к проблеме - с точки зрения многопоточности. Скорее всего, нет ничего, что настраивало бы переменную так, чтобы инструмент статического анализа показал вам неправильное значение, скорее, стратегия синхронизации и блокировки вокруг этой переменной должна быть исследована на предмет потенциальных дыр.

В качестве быстрого исправления , вы можете заключить это значение в AtomicLong .

4
ответ дан 18 December 2019 в 10:46
поделиться

Многопоточное программирование довольно сложно, но есть инструменты IDE, которые могут помочь. Если у вас есть intellij IDEA, вы можете использовать функцию Анализ потока данных , чтобы определить, где что-то изменится. Если не покажет вам поток в реальном времени (это инструмент статического анализа), но он может дать вам отличный старт.

В качестве альтернативы, вы можете использовать некоторые аспекты и просто распечатать значение переменной везде, но полученная отладочная информация будет слишком сложной, чтобы иметь такое значение.

Решение состоит в том, чтобы избежать разделения состояния между потоками. Используйте неизменяемые объекты и программируйте функционально.

2
ответ дан 18 December 2019 в 10:46
поделиться

Я согласен - если значение изменяется только через сеттер (независимо от того, какая организация) - а так и должно быть - тогда лучший способ - изменить сеттер, чтобы отслеживать за вас (трассировка стека печати при каждой настройке, возможно, только когда задано определенное значение, если это снижает шум)

2
ответ дан 18 December 2019 в 10:46
поделиться

1) Предположим, что foo - это имя вашей переменной, вы можете добавить что-то вроде этого в метод установки:

try {
  throw new Exception();
}
catch (Exception e) {
  System.out.println("foo == " + foo.toString());
  e.printStackTrace();
}

Насколько хорошо это будет работать, зависит от того, как часто вызывается установщик . Если он вызывается тысячи раз за время выполнения вашей программы, у вас могут возникнуть проблемы с поиском неверного значения во всех трассировках стека. (Я использовал это раньше для устранения проблемы, подобной вашей. У меня это сработало.)

2) Если вы можете запустить свое приложение в отладчике и , вы можете определить программно неверные значения для вашей переменной , то вы можете установить точку останова в установщике в зависимости от того, что делает значение плохим. Но для этого нужно, чтобы вы могли написать тест на плохие качества, а вы, возможно, не справитесь.

3) Поскольку вы сказали (в последующем редактировании), что проблема заключается в обнулении старших 32 бита, вы можете специально проверить это перед печатью трассировки стека. Это должно сократить объем отладочной информации настолько, чтобы ею можно было управлять.

1
ответ дан 18 December 2019 в 10:46
поделиться

Две вещи:

Во-первых, мне кажется, что какой-то вызывающий объект обрабатывает свою метку времени в целочисленном контексте, теряя ваши старшие 32 бита. Возможно, как предположил Ишай , это связано с потоками, но сначала я бы посмотрел на выполняемые операции. Однако, естественно, вам необходимо убедиться, что ваше значение обновляется «атомарно» - либо с помощью AtomicLong, как он предложил, либо с помощью какого-либо другого механизма.

Помимо этих предположений, учитывая, что вы теряете максимум 32 бита, и вы знаете, что прошло миллисекунды с эпохи, ваш установщик может принудительно обеспечить достоверность : если предоставленное значение меньше отметки времени при запуске программы, это неверно, поэтому отклоните его и, конечно же, распечатайте трассировка стека.

1
ответ дан 18 December 2019 в 10:46
поделиться

В своем вопросе вы говорите о «переменной», которая имеет неправильное значение, и предлагаете попробовать «обернуть значение классом». Возможно, я слишком много вхожу в ваш выбор слов, но хотел бы узнать немного больше о дизайне.

Является ли рассматриваемое значение примитивом? Это поле большого сложного объекта, совместно используемого потоками? Если это поле какого-то объекта, является ли этот объект DTO или он реализует поведение, зависящее от предметной области?

В общем, я согласен с предыдущими комментариями, реинструментирующими объект, «переменная» которого является полем , но дополнительная информация о природе и использовании этой переменной поможет составить более точные предложения.

0
ответ дан 18 December 2019 в 10:46
поделиться

Судя по вашему описанию, я не знаю, означает ли это, что фактическая отладка приложения в реальном времени невозможна, но если это так, то в зависимости от вашей IDE существует множество параметров отладки. доступно.

Я знаю, что с помощью Eclipse вы можете, например, устанавливать условные точки останова в методе установки. Вы можете указать приостановку, только когда значение будет установлено на определенное значение, и вы также можете фильтровать по потоку, если вы хотите сосредоточиться на конкретном потоке.

0
ответ дан 18 December 2019 в 10:46
поделиться

Я лучше оставлю точку останова внутри установщика. Eclipse позволяет вам это делать.

Есть некоторая IDE, которая позволяет вам останавливать (ждать выполнения следующей инструкции) программу, если значение переменной изменяется.

0
ответ дан 18 December 2019 в 10:46
поделиться

IMO the best way to debug this type of problem is using a field modification breakpoint. (Especially if you're using reflection extensively)

I'm not sure how to do this in eclipse, but in intellij you can just right click on the field and do an "add breakpoint".

0
ответ дан 18 December 2019 в 10:46
поделиться
Другие вопросы по тегам:

Похожие вопросы: