Я пишу часть веб-приложения PHP (которое будет использоваться в конкурсе на поиск ошибок в школе), где пользователь должен найти ошибки в данной программе Java. В рамках этого, когда программа Java выполняется, мы хотим выделить строки источника Java-программы, в которой выполнялся код. Для этого нам нужны только номера строк исходного кода, т. Е. Путь к коду (или он называется покрытием кода?). Мы выделим строки в исходном файле, используя номера строк.
Мы будем использовать shell-exec () для PHP, чтобы выполнить программу Java и инструмент для получения кода (независимо от того, что будет). Каков самый простой способ получить номера строк кода?
Большое спасибо!
Вот картина, которая описывает, что нам хотелось бы
PHP взаимодействует с кодом, что означает, что он запускается через источник каждый раз, когда вы запускаете программу. Это может привести к взрыву при чтении кода (что делает распечатки номера строки тривиальными); однако он часто дорог другими способами, так как вы не можете глубоко оптимизировать (или выполнить проверку ошибок перед запуском).
Java компилирует свой код на язык сборки JVM, называемый «байт-код». Это означает, что то, что работает, обычно не имеет доступа (или даже использует) исходный код. Тем не менее, есть методы. Скомпилированный Java-класс имеет возможность добавлять «дополнительные данные», а один из этих «дополнительных элементов данных» – это таблица номеров строк , которая является индексом, позволяющим кому-то, выполняющему сборку, «искать» номер строки, когда компилятор записывал ее ,
Это обычно работает нормально, учитывая, что: компиляторы часто не маркируют каждую инструкцию, исходный код может быть недоступен, оптимизация может сделать некоторые внутренние фрагменты кода недействительными способами, которые облегчают указание на текст входного кода.
Как инструменты исправления кода «исправляют» это то, что они обычно вставляют в код (на уровне сборки) большое количество команд, которые эффективно действуют как протоколирующие операторы в формате, который позволяет инструменту определять, какой путь через код был фактически соблюден , Затем он отображается как можно лучше в таблицу номеров строк, а затем используется для выделения строк в исходном исходном файле.
Если вы хотите что-то с более точным разрешением (что-то, что может обработать, какая часть строки была выполнена), вам нужно копать глубже. В конце концов вы даже можете подумать о написании собственного компилятора (или расширения компилятора), который сохранит вашу собственную таблицу номеров номеров, которая преодолеет недостатки существующих решений.
Трюки, такие как исключение бросания (как сказал Шивен) и разбор номера строк, работают; однако они загрязняют ваш код нечетной обработкой исключений для элементов, которые действительно не являются исключительными, просто для «получения номера строки». Из-за беспорядка кода и, как правило, плохого выполнения исключений, я стараюсь избегать таких решений (но они действительно работают).
В любом случае, надеюсь, это даст вам представление о том, почему он не всегда работает точно так же, как PHP.
Взгляните на Cobertura. Он вычисляет охват и тому подобное, и если он этого еще не делает, должно быть относительно легко добавить номер строки, который он собирает. Это очень хакерская попытка сделать это, но это так медленно, что вы не сможете использовать его в производстве https://bitbucket.org/jowu/myriapod/wiki/Home
Вы можете получить linenumber, если вы скомпилируете программу с параметром -g, выполните printStackTrace (), запишите вывод трассировки и извлеките из него номер строки.
Я никогда не делал и не видел ничего подобного, но это похоже на интересную проблему. Я думал бы использовать java debugger (jdb) для запуска кода, а не только для java
команды.
Вы можете переходить через код по строкам (через команду step
в jdb), и каждый раз, когда строка выполняет свой номер строки, вырывается. Для этого потребуется небольшая помощь со стороны PHP (она должна будет анализировать номер строки, а также выполнить команду следующего шага), но номера строк есть. Вот пример вывода из очень простой java-программы.
Java (TestClass.java)
public class TestClass { public static void main(String[] args) { System.out.println("foo"); System.out.println("bar"); } }
jdb (jdb TestClass после запуска javac TestClass.java
)
Initializing jdb ... > stop at TestClass:3 Deferring breakpoint TestClass:3. It will be set after the class is loaded. > run run TestClass Set uncaught java.lang.Throwable Set deferred uncaught java.lang.Throwable > VM Started: Set deferred breakpoint TestClass:3 Breakpoint hit: "thread=main", TestClass.main(), line=3 bci=0 3 System.out.println("foo"); main[1] step > foo Step completed: "thread=main", TestClass.main(), line=4 bci=8 4 System.out.println("bar"); main[1] step > bar Step completed: "thread=main", TestClass.main(), line=5 bci=16 5 } main[1] step > The application exited
Попробуйте обратиться к этой ссылке JVMDI
Вы можете попробовать получить доступ к значениям счетчика программ, а затем сопоставить их с линиейNumberTable. Или я думаю, что у JVMDI есть метод, который может получить доступ к номеру строки исполняемого кода. Я не уверен в последнем, ссылаюсь на ссылку выше и надеюсь, что это поможет.