обнаружение циклической ссылки в объекте

#java

#java

Вопрос:

Предположим, у вас есть объект Java, можно ли определить, где он существует circular references inside that java object ?

Я хотел бы услышать, существует ли библиотека для решения этой проблемы.

Заранее спасибо.

Ответ №1:

Будьте осторожны, это нетривиальная задача, но вы уже знаете это, верно? 😉

В Java существует реализация IdentityHashMap, которая предназначена для использования в таких случаях.

Ответ №2:

Концептуально простой, но может быть довольно сложным в реализации.

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

Добавьте интерфейс к каждому классу и реализуйте метод «search yourself» в каждом классе. Метод получает список объектов и возвращает код возврата. Метод сравнивает свой собственный адрес с каждым объектом в списке, возвращая true (т. Е. Цикл найден), если один из них совпадает. Затем (если совпадений нет) он добавляет свой собственный адрес в список и вызывает, в свою очередь, метод «search yourself» для каждой ссылки на объект, которую он содержит. Если какой-либо из этих вызовов приводит к коду возврата true, который возвращается, в противном случае возвращается false. (Это «рекурсивный поиск в глубину».)

Если вы не «владеете» классами, то вы должны использовать отражения для реализации по существу вышеупомянутого алгоритма без изменения классов.

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

Комментарии:

1. (IdentityHashMap был бы хорошим способом реализовать список объектов.)

2. Можно также заменить список объектов битовой маской, при этом позиция данного объекта в маске присваивается (с использованием глобального счетчика) при первом поиске объекта.

3. Конечно, вы, вероятно, можете наилучшим образом реализовать алгоритм, добавив поля к объектам. Для каждого объекта требуется bool, два целых числа и указатель на объект вашего интерфейса «поиск самостоятельно». Рекурсия не требуется, и нет опасности переполнения стека. Будет выполняться менее чем за время bM, где N — общее количество объектов, а M — общее количество указателей между объектами.

Ответ №3:

Немного боковой ответ, но как насчет использования, net.sf.json.JSONObject.fromObject(...) которое проверяет циклические ссылки и выдает исключение, если таковые обнаружены. Кроме того, вы можете настроить библиотеку для обработки циклических ссылок по-другому, если это необходимо. Вам пришлось бы написать средство получения для тех членов класса, которые существуют в циклических отношениях, поскольку именно это JSONObject использует для создания JSON.

Комментарии:

1. Спасибо. даже я только что попробовал использовать XStream json, я получил это: com.thoughtworks.xstream.core. TreeMarshaller$ CircularReferenceException: но тогда я не знаю, где это циклическая ссылка. Есть идеи?

2. Для этой json-библиотеки вы можете зарегистрировать CycleDetectionStrategy и получить доступ к «повторяющемуся» объекту. Возможно, было бы возможно сделать что-то подобное с XStream, но по какой-то причине XStream API у меня в данный момент не работает, поэтому я не могу проверить!

3. Спасибо. есть идеи, если бы я только что попробовал: JSONObject JSONObject = JSONObject.fromObject(MyModel ); и я получил это исключение: Исключение в потоке «main» java.lang. Ошибка NoClassDefFoundError: org/apache/commons/lang/exception/NestableRuntimeException Спасибо!

4. Нет, я понял это: net / sf /ezmorph /Morpher

5. Вам не хватает зависимостей библиотеки, которые задокументированы на главной странице .

Ответ №4:

Это кажется простой задачей для программирования. Используйте Java Reflection API для обхода графика объектов Java и сбора посещенных объектов. Если вы посещаете объект, который уже находится в наборе, это означает, что должен быть контур. Для обхода используйте алгоритмы BFS или DFS.

Ответ №5:

Вам не нужна никакая библиотека. Это простой алгоритм поиска по ширине и API отражения. Конечно, вы можете попытаться найти библиотеку, реализующую этот алгоритм.