Сообщество Java раскололось из-за непрекращающихся споров по поводу мобильности, эффективности, стратегии в отношении Java. Дебатируется даже вопрос, что же такое Java - язык или платформа. В своей статье я хотел бы высказать некоторые соображения на этот счет и пояснить, почему мы так радеем за Java. Я также попытаюсь проиллюстрировать, как провалились попытки противостоять "воле Internet".
Так что же все-таки представляет из себя Java?
Java - это язык программирования с четко определенным набором API-интерфейсов и библиотеками классов; язык и API могут совместно образовать согласованное представление любой платформы. Java можно называть метаплатформой или представлением какой-либо существующей платформы, сути это не меняет - с помощью Java-совместимой виртуальной машины и API этот язык позволяет выполнять программы на любых машинах без каких-либо изменений. Таким образом, Java обеспечивает однородное представление гетерогенной по своему характеру сети.
Язык Java приобрел такое важное значение прежде всего потому, что он позволяет практически незаметно осуществлять распространение программного обеспечения по Сети. До появления Java языка программирования для Internet не существовало. Если бы в то время был создан другой язык, в котором присутствовал бы ключевой элемент - мобильность, то Java, вполне возможно, не пользовался бы таким успехом. Возьмем, к примеру, Visual Basic, предшественника Java, который пользовался огромным успехом. Он не получил той массовой общественной поддержки, которой удостоился Java. Дело в том, что Visual Basic не может похвастаться ни мобильностью, ни безопасностью, а при его разработке не учитывалось наличие Сети. Visual Basic - пример все той же устаревшей ограниченной системы воззрений, связанной с персональными компьютерами. Он используется приблизительно в 80% компьютеров мира, однако сообщество, очевидно, считает его недостаточно "массовым", чтобы говорить о свершившейся революции.
Когда телефон есть у каждого человека, от него гораздо больше пользы, кроме того, это очень удобно. Точно так же и возможность выполнять программы где угодно ценится гораздо выше, чем возможность выполнять их лишь на 80% машин.
Мобильность? Все зависит от...
Как быть с последними результатами статистических исследований, которые говорят о том, что примерно половина программ на Java не может выполняться на всех машинах? Эти исследования еще не доказывают, что Java не является мобильным языком. Однако они позволяют утверждать, что программисты не пользуются преимуществами предусмотренных в Java механизмов написания мобильного кода. То, что вы пишете программы на Java, еще не означает, что ваша программа подойдет для любой платформы. Приведу пример. Перед вами Java-код, который не является мобильным (и не будет выполняться так, как задумал его создатель), как не будет мобильным и любой другой подобный код на любом мобильном языке.
File f = new File("/usr/dict/words");
Очевидно, что файл /usr/dict/words подходит не для любой платформы. Более того, использование в качестве разделителя файлов обратной косой черты по определению несовместимо с мобильностью; наличие этой черты делает непереносимым и содержащее данную строку приложение. При создании графических интерфейсов можно столкнуться со множеством аналогичных примеров, например когда вы рассчитываете на определенные размеры шрифта или экрана. Совершенно ясно, что если вы запрашиваете окно 800х600 на экране с разрешением 640х480, ваша программа не будет работать. Инициатива 100% Pure Java - это попытка заставить программистов обратить внимание на проблему переносимости.
Java обеспечивает необходимые инструменты для переносимости всего, что угодно, например управляющих программ графической компоновки (GUI layout managers), Unicode, "культурной среды" и т. д. При этом вам не придется полагаться на специальные хакерские решения вроде тех, которые программисты часто применяют в C++. Проблемы с переносимостью можгут быть вызваны и еще одним фактором: возможными ошибками и несовместимостью различных разработок Java. Однако, как и в случае с любым сложным программным обеспечением, со временем подобных проблем будет становиться все меньше. JavaSoft и ее партнеры уже сформировали Центр по проблемам переносимости и настройки Java (Java Porting and Tuning Center), который займется улучшением платформенной совместимости и сокращением периода запаздывания между выпуском JDK и его реализацией различными производителями.
Действительно ли Windows важнее?
Зачем беспокоиться о переносимости? Не лучше ли вместо этого обратиться к громадному рынку Windows, который охватывает 80% мирового рынка компьютеров? Не правда ли, такая постановка вопроса заставляет нас перенестись в начало 80-х, тогда ведь тоже любили спрашивать: "Зачем мне ПК, если есть мэйнфрейм?" Подобно первым ПК, Java поддерживает новую систему воззрений на вычислительный процесс, которая имеет несомненные преимущества над прежними. Основное преимущество состоит в том, что если вы создаете продукт на основе технологии Windows, то процесс программирования будет напоминать стрельбу по движущейся мишени. Дело в том, что с ростом популярности Internet большинству компаний пришлось переосмыслить свою стратегию. Даже Microsoft совершила впечатляющий поворот на 180%, осознав влияние Internet. Microsoft не стала бы лицензировать язык Java (представляющий угрозу ее бизнесу), если бы Internet не заставила ее это сделать. Сеть фактически проигнорировала VBScript/BlackBird, и Microsoft волей-неволей пришлось пойти навстречу разработчикам, чтобы не оказаться вне игры. Игнорируя Сеть, вы сильно рискуете.
А как насчет производительности?
Пусть язык Java учитывает потребности Сети, пусть он обладает стопроцентной переносимостью, но не намного ли он медленнее C++? Ответ прост: нет. Ни один из этих языков не имеет серьезного преимущества в скорости благодаря каким-то особым качествам. В настоящее время Java медленнее потому, что он интерпретируемый, частично интерпретируемый или просто компилируется хуже, чем C++. Предварительная (статическая) компиляция Java-программ сократит время их выполнения, приблизив его ко времени выполнения программ на C++, но резко снизит их переносимость и безопасность. Однако можно воспользоваться компилятором just-in-time (JIT). Он позволит сохранить ту степень мобильности и безопасности, которую обеспечивает Java, путем компиляции программы непосредственно перед ее выполнением (это динамическая компиляция). К сожалению, JIT имеет одно ограничение - при его использовании сумма времени компиляции и сокращенного времени выполнения программы должна быть меньше времени простой интерпретации программы; поэтому для программ, которые выполняются только очень короткое время, использование JIT не имеет смысла.
При работе с длинными программами динамическая компиляция имеет серьезные преимущества перед статической. Статическая компиляция может оптимизироваться лишь для одного центрального процессора (обычно с наименьшим общим знаменателем, например Intel 386). В то же время динамическая компиляция позволит генерировать при каждом отдельном прогоне программы специализированный код. Переменные времени статической компиляции фактически являются константами времени динамической компиляции. Рассмотрим часть объектно-ориентированного кода, в котором метод снабжен ссылкой на переменную объектного типа (type Object).
int h = obj.hashCode();
При статической компиляции программы компилятор не знает, каким будет реальный тип объекта obj во время выполнения, а следовательно, не может знать и того, какая версия метода hashCode окажется вызвана: включение (inlining) метода невозможно. Однако во время выполнения тип obj известен и компилятор может включить hashCode. Например, если известно, что obj имеет тип Integer (целый), то компилятор создаст что-нибудь типа:
int h = ((Integer)obj).value; // hashCode inlined
При использовании языка С++ следует провести просмотр виртуальной таблицы (virtual table), найти адрес функции, а затем вызвать эту функцию:
int h = (*(obj.vtable[hashCode-vtable-offset]))();
Осуществить с помощью динамического компилятора присваивания int значительно легче, чем вызывать виртуальный метод, особенно после того, как его включенная версия полностью окажется в кэш-памяти. В то же время использование версии С++ усложнит кэш-память и, возможно, повлечет за собой пропуск страниц, соответствующих ссылкам виртуальной таблицы.
Так почему же такую чудесную оптимизацию не осуществляют существующие компиляторы JIT? Ну, во-первых, это сложно. Во-вторых, подобно объектно-ориентированному программированию, которое преодолело путь от научных исследований до промышленного использования за 20 лет, такой сложный процесс, как компиляция "на лету", многие годы существовал лишь на бумаге. Сейчас множество ведущих ученых, занимавшихся этой технологией, работают на корпорацию Sun. Первая рабочая реализация подобной технологии оптимизации - HotSpot - уже на подходе. Она создается в JavaSoft и войдет в новую версию JDK.
Набор Swing
Итак, вы поверили в то, что язык Java обладает переносимостью и эта переносимость важна для вас, и наконец узнали, что вскоре Java будет обеспечивать достаточно высокую производительность. Но вы можете задать вопрос: "Достаточно ли оконной библиотеки AWT для создания профессиональных приложений?" Многие программисты ответили на этот вопрос отрицательно и разработали свои собственные оконные библиотеки, используя мелкие компоненты, которые поставляли со своими приложениями. Компоненты Swing в созданных JavaSoft классах Java Foundation Classes (JFC) входят как раз в такую библиотеку, хотя ее основой станут все же JFC (они присутствуют в любой реализации JDK). Swing - это превосходный профессиональный набор приспособлений (widgets) и управляющих элементов для программ на базе форм. Однако вместо того, чтобы верить мне на слово, просто загрузите последнюю версию библиотек JavaSoft и проверьте демонстрационный вариант набора Swing в работе. Он говорит сам за себя.
Sun против Microsoft?
Если язык Java такой замечательный, то почему Sun и Microsoft все время спорят из-за него? Если говорить коротко, то вполне понятно, что Microsoft обязана зарабатывать деньги для владельцев своих акций. Поэтому Microsoft немало заинтересована в том, чтобы заставить всех писать приложения, которые работают исключительно под Windows. Неудивительно, что к приложениям, которые не зависят от определенной операционной системы, она особой любви не питает. Microsoft приняла язык Java в надежде, что сможет убедить разработчиков в своей любви к нему, а также в том, что она действительно лидирует в данной отрасли. Впоследствии Microsoft смогла бы отвлечь внимание разработчиков, заставив их рассматривать Java всего лишь как еще один способ использования господствующей технологии Microsoft, такой, например, как ActiveX (которая явно готова испустить дух и уступить место DNA), AFC (Application Foundation Classes) и J/Direct.
Решение Microsoft удалить со своего Web-узла все апплеты Java вряд ли способствовало укреплению ее репутации приверженца Java. Стратегия Microsoft состоит в том, чтобы представить Java в ряду прочих языков программирования. Прошу прошения, но если бы он был всего лишь одним из многих языков, то вряд ли представлял бы особый интерес и, следовательно, не привлек бы такого внимания. (О существовании Java знает даже моя матушка. А вот о Visual Basic или С++ она не осведомлена.) Java представляет собой новую вычислительную модель и обеспечивает вашим приложениям платформенную независимость. Важно отметить и то, что использование Java (языкового компонента) - это не особенно удачный способ получить доступ (при помощи J/Direct) к API-интерфейсу на базе указателей вроде Win32, написанному на С и с учетом требований С++ и не позволяющему эффективно очищать память.
Internet - это величайшее государство, где царит анархия, государство, пользующееся огромным успехом. Internet никто не управляет, а успеха здесь прежде всего добивается тот, кто плывет по течению. Java позволяет осуществлять в Internet распределенные вычисления и безопасные перемещения кода. Появление этой технологии послужило толчком к началу революции, которая намного превосходит по значению революцию персональных компьютеров.
В заключение я хочу напомнить, что ключевой элемент этой революции - переносимость Java, однако при программировании вы должны самостоятельно заботиться о переносимости своих продуктов (инициатива "100 % Pure Java" обеспечивает для этого и инструменты, и ресурсы). В JDK 1.1 устранены многие недостатки, характерные для первой версии. А новые API-интерфейсы, которые будут включены в базовые библиотеки JDK 1.2, позволят быстро проводить разработку сложных программ. Учитывая, что скорость выполнения программ в скором времени будет сравнима со скоростью выполнения программ на C++ (а в некоторых случаях превзойдет ее) при статической компиляции, Java полностью оправдает ожидания разработчиков.