- •Раздел 4. Разработка по Тема 4.1. Проектирование интерфейса с пользователем
- •4.1.1. Типы пользовательских интерфейсов.
- •4.1.2. Пользовательская и программная модели интерфейса.
- •4.1.3. Разработка диалогов.
- •4.1.4. Основные компоненты графических пользовательских интерфейсов.
- •Тема 4.2. Реализация графических пользовательских интерфейсов.
- •4.2.1. Диалоги, управляемые пользователем.
- •4.2.2. Диалоги, управляемые системой.
- •4.2.3. Использование метафор.
- •4.2.4. Технология Drag and Drop.
- •4.2.5. Интеллектуальные элементы.
- •4.3.1. Базовые типы данных.
- •Константы
- •Область действия имен
- •4.3.2. Указатели и адресная арифметика.
- •4.3.3. Составные типы данных. Структуры
- •Битовые поля
- •Определение типов
- •Перечислимые типы
- •4.3.4. Выражения и операции.
- •4.3.5. Управляющие конструкции. Условные операторы
- •Операторы циклов
- •4.4.1. Статические одномерные массивы.
- •4.4.2. Статические многомерные массивы.
- •4.4.3. Динамические массивы.
- •4.4.4. Массивы указателей.
- •4.5.1. Стеки.
- •4.5.2. Очереди.
- •4.5.3. Списки.
- •4.5.4. Бинарные деревья.
- •4.6.1. Объявление классов и экземпляров классов.
- •4.6.2. Инкапсуляция данных и методов.
- •4.6.3. Конструкторы классов.
- •Конструктор по умолчанию
- •Конструктор копирования
- •4.6.4. Деструкторы классов.
- •4.7.1. Разделы в описании класса.
- •4.7.2. Friend-конструкции.
- •4.7.3. Статические члены классов.
- •4.7.4. Использование описателя const в классах.
- •4.8.1. Вложенность классов.
- •4.8.2. Наследование данных и методов.
- •4.8.3. Типы наследования.
- •4.9.1. Полиморфизм раннего связывания.
- •4.9.2. Полиморфизм позднего связывания и виртуальные функции.
- •4.9.3. Абстрактные методы и классы.
- •4.10.1. Функции консольного ввода-вывода.
- •4.10.2. Функции файлового ввода-вывода.
- •4.10.3. Использование библиотеки классов потокового ввода-вывода.
- •4.11.1. Перегрузка операций.
- •4.11.2. Шаблоны функций.
- •4.11.3. Шаблоны классов.
- •4.11.4. Обработка исключений.
- •Тема 4.12. Com-технология.
- •4.12.1. Основные понятия.
- •4.12.2. Типы интерфейсов.
- •Свойства интерфейсов
- •Типы интерфейсов
- •4.12.3. Типы com-объектов.
- •4.12.4. Фабрика классов.
- •Тема 4.13. Построение com-сервера.
- •4.13.1. Язык idl.
- •Содержимое файла idl
- •4.13.2. Определение пользовательского интерфейса.
- •4.13.3. Реализация пользовательского интерфейса.
- •4.13.4. Создание тестового клиента.
- •Тема 4.14. Обзор платформы ms .Net.
- •4.14.1. Общая идея архитектуры .Net.
- •4.14.2. Достоинства и недостатки .Net.
- •4.14.3. Схема трансляции программ в .Net.
- •4.14.4. Язык msil.
- •4.14.5. Объектно-ориентированная модель .Net.
4.14.3. Схема трансляции программ в .Net.
Компилятор JIT является ключевым средством платформы .NET и жизненно важной составляющей в реализации попытки Microsoft сделать так, чтобы управляемый код работал с большей производительностью, чем неуправляемый код.
Проблема производительности возникает из-за того, что код компилируется в промежуточный язык, и это может стать неожиданностью для некоторых разработчиков, В конце концов, одним из недостатков Jaya является то, что процесс трансляции с байт-кода Java в исполняемый код в процессе выполнения программы означает потерю производительности. Однако существует все же большая разница, заключающаяся в том, что байт-код Java интерпретируется, a IL компилируется. Более того, JIT-компилятор компилирует не всю программу сразу (что может привести к излишне долгому запуску программы), а лишь кусок кода и именно тогда, когда он вызывается (отсюда название JIT-компилятора: just-in-time — вовремя). После того как код единожды откомпилирован, получившийся в результате машинный код сохраняется в памяти до тех пор, пока не будет осуществлен выход из программы, поэтому при следующем запуске того же самого кода его уже не потребуется компилировать. Microsoft считает, что это более эффективный процесс, чем компиляция всей сборки сразу, так как велика вероятность того, что большая часть кода сборки не будет выполняться во время одного конкретного запуска программы. При использовании JIT- компилятора такой код вообще не придется компилировать.
Этим объясняется, почему исполнение управляемого кода на IL будет почти таким же быстрым, как и исполнение родного маши иного кода, но не объясняется, почему Microsoft ожидает получить еще и улучшение по производительности. А дело в следующем: так как окончательная стадия компиляции происходит уже в процессе исполнения, JIT-компилятор точно знает, на каком процессоре будет работать программа. Это означает, что код может быть оптимизирован под использование тех особенностей, которые предлагаются каждым конкретным процессором.
Традиционные компиляторы оптимизируют код, но они могут выполнять только оптимизацию, не зависящую от конкретного процессора. Это происходит из-за того, что современные компиляторы осуществляют компиляцию сразу в машинный код перед тем, как программа будет отправлена потребителю. Следовательно, компилятор не знает, на каком процессоре будет исполняться код. Ему могут быть известны лишь общие сведения, что это будет процессор семейства х86 или процессор Alpha. Visual Studio 6, например, оптимизирует код для процессора Pentium, поэтому такой код не сможет воспользоваться преимуществами процессора Pentium III. Напротив, JIT-компилятор может выполнить ту же оптимизацию, что и Visual Studio 6, но вдобавок оптимизировать код для того процессора, на котором он будет исполняться.
4.14.4. Язык msil.
Часто CIL называют псевдоассемблером, так как он определяет набор команд некоего процессора. Однако в данном случае процессором является не кусок кремния, a CLR. При написания программ для .NET Framework знать CIL нужно не более, чем ассемблер х8б для программирования под Windows. И все же элементарные познания в СП. могут быть полезны, если вам понадобится узнать, почему какой-то метод FCL работает не так, как вы этого ожидали. У вас нет исходного кода FCL. но есть CIL CIL содержит примерно 100 команд. Некоторые из них — типичные низкоуровневые, аналогичные командам микропроцессоров, например, команды сложения двух значений (ADD) или перехода, если два значения равны (BEQ). Другие, более высокого уровня, редко встречаются в аппаратных наборах команд. Так, NEWOBJ создает экземпляр объекта, a THROW генерирует исключение. Благодаря такому богатству набора команд CIL, код на языке высокого уровня, таком как С» или Visual Basic .NET, зачастую порождает при компиляции удивительно малое число команд.
CIL использует стековую модель исполнения. Если процессоры х8б для обработки значений загружают их в регистры, то CLR помещает их в вычислительный стек. Чтобы сложить два числа, они копируются в стек, вызывается ADD, и результат считывается из стека. Копирование значения из памяти в стек называется загрузкой (loading), а копирование в обратном направлении — сохранением (storing). В СП, есть несколько команд загрузки и сохранения. Например, LDLOC загружает в стек значение по некоторому адресу в памяти, a STLOC копирует значение из стека в память, удаляя его из стека,
В качестве примера работы C1L, рассмотрим фрагмент программы С#, в котором объявляются и инициализируются две переменные, затем они складываются, и сумма записывается в третью переменную;
int а = 3; irt b = 7;
irt с = а + Ь;
Ниже приведен CIL, сгенерированный компилятором Microsoft C#:
ldc.14.3 // Загрузить в стек 32-разрядное (14) число 3.
stJ.oc.0 // Сохранить его в локальной переменной 0 (а).
ldc.14,7 // Загрузить на отек 32-разрядное (14) число 7.
stloc.1 // Сохранить его в локальной переменной 1 (Ь).
ldloc.0 // Загрузить в стек локальную переменную 0.
1йЮс,1 // Загрузить в стек локальную переменную 1.
add // Сложить два числа и получить сумму в стеке.
stloc.2 // Сохранить сумму в локальной переменной 2 (с).
Как видите, CIL весьма прост. Однако непонятно, как выделяется память для локальных переменных а, Ь и с (для CIJR это локальные переменные О, I и 2). С помощью метаданных. При компиляции в метаданные метода помещаются сведения о том, что объявлены три локальных 32-разрядных целых переменных, CLR считывает эти сведения и выделает память для локальных переменных перед началом исполнения метода. Если дисассемблировать метод с помощью ILDASM, метаданные будут отображены как директива компилятора:
.locals init (int32 V_0, // Локальная переменная 0 (а). int32 V_1, // Локальная переменная 1 (Ь). int32 V_2) // Локальная переменная 2 (с).
Это превосходный пример того, как важны метаданные /тля CLR. Они служат не только для проверки безопасности типов, но и для подготовки контекста исполнения. Кстати, если исполняемый модуль С* скомпилирован с ключом /DEBUG, то ILDASM отобразит настоящие названия переменных вместо условных обозначений вроде V_0.
В .NET Framework SDK есть документ, описывающий весь набор команд СП. в мельчайших подробностях. Не буду помещать здесь полный список команд CIL — приведу лишь наиболее часто используемые команды и их краткое описание.
ILDASM, которая позволяет посмотреть метаданные, является и прекрасным дизассемблером CIL, Запустите ILDASM и откройте с ее помощью одну из библиотек Systcm.'.dll в каталоге \%SystemRoot%\Microsoft.NET\Framework\vl.0.mmK. Эти DLL относятся к библиотеке классов .NET Framework. Затем выберите какой-нибудь метод для дезассемблирования. Методы легко отыскать — они обозначены малиновыми прямоугольниками. Дважды щелкнув метод, вы увидите его CIL вместе с директивами компилятора, сгенерированными по метаданным метода. Более того, ILDASM — это двунаправленный дизассемблер, т. е. ему на вход можно подать дисассемблированный код и снова получить CIL
Разработчики часто поднимают проблему интеллектуальной собственности; если каждый может дезассемблировать FCL, что помешает конкуренту дизассемблировать чужой продукт? Восстановление исходного текста no CIL — нетривиальная задача, но это проще, чем восстановить его по коду х86. Кроме того, декомпиляторы, генерирующие по CIL исходный текст на С#, имеются в свободном доступе в Интернете, Как же защитить свою интеллектуальную собственность?
Короткий ответ — по обстоятельствам. Код, исполняемый только на серверах, например, Web-сервисы XML, недоступен пользователям и, таким образом, не может быть дизассемблирован, если только кто-нибудь не проникнет сквозь ваш брандмауэр. Код, поставляемый конечным пользователям, может быть зашифрован утилитами.