Привет, Вы узнаете про двоичная совместимость, Разберем основные ее виды и особенности использования. Еще будет много подробных примеров и описаний. Для того чтобы лучше понимать что такое двоичная совместимость, бинарная совместимость , настоятельно рекомендую прочитать все из категории Разработка программного обеспечения и информационных систем.
Двои́чная совмести́мость, бина́рная совмести́мость (англ. binary compatibility) — вид программной совместимости, позволяющий программе работать в различных средах без изменения ее исполняемых файлов. Этот термин часто используется в значении «совместимость операционных систем», и в таком случае означает способность уже скомпилированной версии программы для одной операционной системы работать в другой операционной системе без перекомпиляции.
К примеру, практически все программы, написанные для Windows 2000, можно запустить в Windows XP — это означает, что Windows 2000 и Windows XP бинарно (двоично) совместимы. двоичная совместимость включает в себя побайтовую совместимость полей загрузки, полную идентичность механизма вызова функций, передачи переменных и получения результата вычислений, и полную реализацию интерфейса программирования. При этом технически реализация может быть совершенно иной, — главное, чтобы были реализованы все вызовы и чтобы они приводили к ожидаемому результату, а каким способом этот результат достигается, решают создатели программы.
Что такое бинарный файл прошивки?
Слом двоичной совместимости означает прекращение поддержки программ и обязательное требование перекомпиляции и возможных исправлений в программе, чтобы она заработала. К примеру, после того, как компания Apple начала использовать в своих компьютерах процессоры Intel, была сломана двоичная совместимость со всеми приложениями, написанными для процессоров PowerPC.
Чтобы не лишиться всех разработанных в прошлом программных продуктов для операционной системы Mac OS, компания Apple использует легкий транслятор Rosetta, переводящий вызовы операционной системы Mac OS для PowerPC в вызовы Mac OS для Intel. Этот пример демонстрирует также возможный метод борьбы со сломом двоичной совместимости. В операционной системе Solaris 10 для x86 существует возможность запускать приложения для Linux без перекомпиляции с помощью BrandZ. На платформе SPARC такая возможность отсутствует. Возможно, многие из вас задавались вопросами вроде «А что будет, если кто-то подложит к моему приложению неправильную версию библиотеки?» . Вопрос хороший, а ответ на него и некоторые другие вы найдете в этом топике. Для затравки задачка: пусть есть два интерфейса и класс, реализующий один из них:
А также класс, в котором есть метод foo , перегруженный для A и B . Этот метод вызывают от экземпляра класса C :
Почему невозможно заработать на бинарных опционах?
Вполне очевидно, что выведется «A». Не менее очевидно, что если сказать, что C implements A, B , то получится ошибка компиляции ( тем, кому последнее не очевидно, могу порекомендовать почитать про то, как происходит выбор методов. Например, в стандарте в разделе 15.12.2 или в более просто описывающих местах ).
Но вот что произойдет, если мы перекомпилируем только C.java , а потом запустим CompatibilityChecker из уже имеющегося класс-файла, является уже более сложным вопросом. Заинтересованы? Прошу под кат!
Static dispatch
Те, кто знают, что перегруженные методы выбираются во время компиляции, могут сообразить, что по этой причине в класс-файле будет сразу записана информация о том, какой же метод вызывать, и потому в результате выведется «A». Проверим это предположение:
Действительно, как можно заметить по инструкции с отступом 19, идет вызов вполне конкретного метода. Впрочем, те, кто слышал про верификатор , могут возразить и предположить, что он заметит, что это какие-то не те пчелы класс C изменился, и швырнет исключение. К счастью, они ошибаются, ведь верификатор проверяет только лишь корректность структуры классов и интерфейсов, а не соответствие версий класс-файлов.
Итак, запустим-таки наш код и убедимся, что изначальное предположение было правильным: выведется действительно «А».
Кроме того, можно предположить, что в виртуальной таблице адресов может оказаться какой-то неправильный адрес, и потому все сломается в рантайме с NoSuchMethodError . Об этом говорит сайт https://intellect.icu . Это предположение тоже ошибочно, так как вызывается метод foo(A) , и в виртуальной таблице он такой один. Другое дело, если бы были наследники, его переопределяющие…
Dynamic dispatch
Пусть у нас есть три следующих класса:
И класс, вызывающий foo в разных вариантах:
Все, конечно же, знают, что поскольку у переотпределенных типов методы выбираются в рантайме, изначальный вывод будет таким:
Самое время сделать пакость, подменив класс-файл от A на результат компиляции следующего кода:
Понять, что в данном случае произойдет, довольно просто. Во-первых, все попытки вызвать методы, где foo вызывается у экземпляпа класса A , точно вылетят с NoSuchMethodError . Среди этих попыток также находится и вызов super.foo() в классе C . Во-вторых, как мы уже видели раньше, метод B.foo() вызовется успешно.
Теперь изменим тактику: снова сделаем A.foo таким, каким он и был, но теперь поменяем B и C , вообще удалив из них переопределение метода foo :
При запуске кода dynamic dispatch обнаружит только по одной записи для A.foo , и потому во всех случаех вызовет его, в результате чего мы увидем в консоли только буквы «A» и полное отсутствие каких-либо исключений.
Продолжим наши изыскания, снова переопределив методы в B и C . После запуска, как мы и можем ожидать, dynamic dispatch обнаружит все записи в виртуальной таблице, и даст точно такой же вывод, как и тот, который мы получили бы, заново перекомпилировав все.
Поля несоответствующих типов
Ранее мы пробовали экспериментировать только с методами. Посмотрим теперь, что бывает с полями. Пусть есть класс, хранящий значение типа int и наследник этого класса:
И, традиционно, потребитель класса B :
Добавим теперь в класс B собственное поле с таким же именем:
Посмотрим, какой байт-код был сгенерирован для CompatibilityChecker :
Этот листинг может сбить с толку, полкольку на отступе 11 в комменте вроде как сказано, что поле принадлежит B. Потому стоит полагать, что при перекомпиляции B мы столкнемся с ошибкой. Однако оказывается, что это вовсе не так. Поскольку физически поле есть только у базового класса, операнд команды putfield указывает именно на то самое нужное поле, в результате чего после изменений код продолжает работать.
А что вообще говорит спецификация?
- Изменение реализации существующих методов, конструкторов или блоков инициализации
- Добавление новых полей, методов и конструкторов существующим классам и интерфейсам
- Удаление приватных полей, методов и конструкторов класса
- Перемещение методов наверх по иерархии классов
- Добавление новых классов и интерфейсов
Возможно, именно из-за такого слабого определения двоично совместимых операций, возникают проблемы.
Как выяснилось, спецификация недостаточно строга, и можно придумать случай, в котором безопасные изменения приведут к ошибке в линковке. Рассмотрим интерфейс, класс, реализующий этот интерфейс, и еще один класс, использующий их:
Произведем два безопасных изменения: добавим метод foo в интерфейс A и изменим реализацию метода main класса CompatibilityChecker :
При запуске, как вы могли понять, произойдет ошика, а именно AbstractMethodError: B.foo()V , чего по идее быть не должно. Эту проблема известна и лежит в самой основе обработки байт-кода Java. Были предложения по исправлению ситуации, но они пока ни к чему не привели.
Итак, ответ на вопрос, профигурировавший в самом начале статьи («А что будет, если кто-то подложит к моему приложению неправильную версию библиотеки?») такой: «А кто ж его знает. Смотря в чем та версия, которая использовалась при компиляции, отличается от той, которая используется в рантайме».
В статье не затронуты некоторые очевидные вещи. Например, что при несовместимых изменениях вроде удаления методов и классов или превращения класса в интерфейс, будут кидаться беспощадные ошибки вроде NoSuchMethodError , NoClassDefFoundError или IncompatibleClassChangeError .
Вау!! Ты еще не читал? Это зря!
- Программное обеспечение
- программирование
- Депрекация
- ошибка совместимости , обратная совместимость , прямая совместимость , совместимость ,
- Совместимость с ошибками , обратная совместимость с известными недостатками
- Режим совместимости
- Совместимость с компьютером
- Устаревание
- Атака на понижение версии
- Эмулятор
- День флага (вычисления)
- Устаревший режим
- Прокладка (вычисление)
- Программная регрессия
- Привязка к поставщику
В общем, мой друг ты одолел чтение этой статьи об двоичная совместимость. Работы в переди у тебя будет много. Смело пишикоментарии, развивайся и счастье окажется в ваших руках. Надеюсь, что теперь ты понял что такое двоичная совместимость, бинарная совместимость и для чего все это нужно, а если не понял, или есть замечания, то нестесняся пиши или спрашивай в комментариях, с удовольствием отвечу. Для того чтобы глубже понять настоятельно рекомендую изучить всю информацию из категории Разработка программного обеспечения и информационных систем
Источник: intellect.icu
Программная реализация логических функций и автоматов
Представление автомата схемой, состоящей из логических элементов наиболее исследованный вид структурной реализации автомата. Другой ее вид — реализация программой. Программа вычисляет (реализует) логические функции f(x1,. xn) = y, если для любого двоичного набора d = (d1. dn ) при начальном состоянии элементов памяти x1 = d1, x2 = d2. xn = dn программа через конечное число шагов останавливается и в ячейке y лежит величина f(d1, d2. dn). Если под сложностью схемы, реализующей автомат, обычно понимается число элементов схемы, то под сложностью программ можно понимать:
n число команд в тексте программы;
n объем промежуточной памяти;
n время вычисления программы, которое характеризуется двумя величинами:
1. Средним временем
2. Максимальным временем ,
где сумма и максимум берутся по всем 2 наборам, а tp — время работы программы на одном наборе s.
Рассмотрим 2 типа программ: операторные и бинарные. Операторная программа не содержит условных переходов, порядок ее команд в точности соответствует нумерации элементов в схеме, а система команд соответствует базису схемы. Элементы схемы нумеруются числами 1. n таким образом, чтобы на любом пути от входа к выходу номера элементов возрастали. При этом номер 1 получит один из входных элементов, а номер n — выходной элемент.
Пусть элемент схемы ei реализует функцию ji и к его входам присоединены выходы элементов ej1, e j2. e jm (некоторые из них, возможно, являются входами схемы), тогда выход такого элемента можно записать:
ai = ji (ej1, e j2,. e jm) при i ¹ n, а выход схемы может быть записан: y = ji(ej1, e j2,. e jm) при i = n. Такая программа будет реализовывать работу заданной схемы. Проблема синтеза операторных программ сводится к проблеме синтеза схем, то есть к вопросам функциональной полноты и минимизации схем. Поскольку операторная программа не содержит условных переходов, то время ее выполнения на любом наборе одно и то же, отсюда
Бинарные программы это программы, состоящие из команд типа y = d; d = и условных переходов.
Замечание. Бинарные программы обладают двумя достоинствами по сравнению с операторными:
1. Отсутствием промежуточной памяти в процессе работы программы. Это позволяет реализовать бинарную программу на постоянных элементах памяти.
2. Более высоким быстродействием.
Пример. Составить для функции f = x1 v Øx2 бинарную и операторную программы.
Решение. Воспользуемся языком С++, будем иметь код:
bool f=0, x1,x2; // описание типа переменных
cin>> x1>>x2; // ввод переменных
switch (x1) // оператор выбора
Источник: studopedia.ru
9. Операторные и бинарные программы.
Рассмотрим 2 типа программ: операторные и бинарные. Операторная программа не содержит условных переходов, порядок ее команд в точности соответствует нумерации элементов в схеме, а система команд соответствует базису схемы. Элементы схемы нумеруются числами 1. n таким образом, чтобы на любом пути от входа к выходу номера элементов возрастали. При этом номер 1 получит один из входных элементов, а номер n — выходной элемент.
Бинарные программы это программы, состоящие из команд типа y = ; = и условных переходов.
Замечание. Бинарные программы обладают двумя достоинствами по сравнению с операторными:
- Отсутствием промежуточной памяти в процессе работы программы. Это позволяет реализовать бинарную программу на постоянных элементах памяти.
- Более высоким быстродействием.
Пример. Составить для функции f = ( x1 v x3 ) x4 v x2) бинарную и операторную программы.
Решение. Воспользуемся языком С++, будем иметь код:
bool f=0, x1,x2,x3,x4,x5 ; // описание типа переменных
cin>> x1>>x2>>x3>>x4>>x5; // ввод переменных
switch (x1) // оператор выбора
case 0: switch(x3)
case 1: switch ( x5)
case 0: switch (x2)
case 1: switch (x4)
case 1: switch (x2)
Операторная программа пишется в базисе . Для этого перепишем заданную функцию, используя формулы де Моргана.
f = (x1 ( ( x5 x2 )
bool f, x1,x2,x3,x4,x5 ; // описание типа переменных
cin>> x1>>x2>>x3>>x4>>x5; // ввод переменных
10. Логические схемы. Элементная база.
Логический вентиль (вентиль) – это своего рода элемент, из которого состоят электронные узлы ЭВМ. Он работает по принципу крана, открывая или закрывая путь сигналам.
Логические схемы предназначены для реализации различных функций алгебры логики и реализуются с помощью трех базовых логических элементов (вентилей, логических схем, переключательных схем). Они воспроизводят функции полупроводниковых схем.
Логические функции отрицания, дизъюнкции и конъюнкции реализуют логические схемы, называемые инвертором, дизъюнктором и конъюнктором.
Логическая функция «инверсия», или отрицание, реализуется логической схемой (вентилем), называемой инвертор.
Дизъюнкцию реализует логическое устройство (вентиль) называемое дизьюнктор
Конъюнкцию реализует логическая схема (вентиль), называемая конъюнктором.
Пример. В двоичной системе таблицу суммирования цифры x и цифры y и получения цифры z с учетом переноса p в следующий разряд можно изобразить таблицей вида:
Источник: studfile.net