■ Независимость от операционной системы. Среды выполнения управляемого кода вместе с их библиотеками обеспечивают разработчикам возможность написания программ на уровне абстракции, расположенном поверх базовой операционной системы. Учитывая тот факт, что пользовательские интерфейсы и модели взаимодействия с пользователем для классов устройств, в которых применяются различные степени абстрагирования верхних уровней, значительно отличаются друг от друга, принцип разработки программ "пишется однажды, выполняется везде" ("write once, run everywhere") вряд ли можно считать практически осуществимым, однако операционная система все еще остается весьма полезным средством обеспечения переносимости приложений на устройства разных классов. Кроме того, возможность создавать автономные (автономные (headless) — не имеющие пользовательского интерфейса) компоненты, способные выполняться на различных устройствах без перекомпиляции, оказывается очень полезной при построении повторно используемых модулей. После того как автономные компоненты заполнены общим кодом, остается лишь реализация зависящих от конкретного типа устройства пользовательских интерфейсов, в которых используются общие модули такого типа.
■ JIT-компиляция (just-in-time — оперативная) и/или интерпретация кода. Существует два метода выполнения управляемого кода: 1) JIT-компиляция, когда IL сначала транслируется в собственные машинные команды процессора, а затем выполняется, и 2) интерпретация, когда просматривается каждая инструкция IL, и для выполнения предусмотренных ею действий вызываются предопределенные библиотеки. Код, получаемый в результате JIT-компиляции, работает быстрее, однако интерпретаторы легче создавать, поскольку они не обязаны знать, как генерировать специфические для процессора команды. Во многих случаях сначала создают интерпретатор, с помощью которого можно быстро перенести управляемый код времени выполнения на новый процессор, и лишь затем создают JIT-компиляторы, позволяющие оптимизировать код для конкретных типов наиболее распространенных процессоров. Один и тот же IL-код может либо интерпретироваться, либо JIT-компилироваться; окончательный выбор остается за теми, кто реализует исполняемый код.
■ Сборка мусора. Сборка мусора — это операция, избавляющая разработчиков приложений от необходимости заниматься утилизацией памяти, используя низкоуровневые функции. Существует множество различных стратегий сборки мусора, каждая из которых оптимизирована для сценариев определенного типа. Исследования в этой области продолжаются, приводя к нахождению все более оптимальных стратегий для самых важных сценариев. Обычной стратегией, применяемой в средах выполнения на мобильных устройствах, является стратегия "отслеживания и очистки" ("mark and sweep"), суть которой состоит в том, что среда выполнения периодически составляет список всех переменных, находящихся в данный момент в области видимости, и отслеживает все объекты, на которые эти объекты ссылаются. Каждый из обнаруженных таким способом объектов снабжается "меткой", указывающей на то, что объект все еще используется. На основании этой схемы создается дерево активных объектов (live-object tree), представляющее полный набор всех объектов, к которым код приложения может получить доступ. После того как все активные объекты отмечены, выполняется операция очистки, которая освобождает все объекты, являющиеся для приложения недоступными. Программы, осуществляющие сборку мусора, представляют собой чрезвычайно сложные системы, так что для оптимизации производительности серверов, настольных компьютеров и мобильных устройств всегда остается масса возможностей. В организациях, занимающихся разработкой сред выполнения управляемых кодов, значительная доля усилий направляется на повышение эффективности стратегий сборки мусора до уровня, способного обеспечить получение максимально возможных производительности и надежности.
■ Контроль версий. Помимо всего прочего метаданные можно использовать для передачи обширной информации, касающихся номера версии компонента и номеров версий компонентов, от которых он зависит. Среды выполнения управляемых кодов, располагающие возможностями контроля версий, способны обеспечивать корректную работу нескольких версий одних и тех же компонентов на одной и той же машине, позволяя каждому компоненту связываться именно с теми компонентами, с которыми он создавался и тестировался. Этот фактор имеет большое значение для обеспечения долговременной устойчивой работы устройств, на которых выполняется множество приложений. Встроенная поддержка контроля версий позволяет избежать конфликтов между ними и предотвратить возникновение как малозначительных, так и явно выраженных проблем, к которым может привести отсутствие надлежащего контроля версий.