Почему Java считается более переносимым, чем другие языки, такие как C ++?

16

Чем отличается «написание конкретной JRE для каждой платформы» для разработчиков Java и «написание компилятора C ++ для каждой платформы» для C ++?

user967316
источник

Ответы:

33

Java компилируется один раз, когда-нибудь запускается C ++ - это когда-нибудь один раз скомпилировать.

Pubby
источник
3
Ну, у вас явно не было большого опыта разработки GUI. (В ожидании Qt ...)
27
Любой, кто заявляет, что C ++ - это «однажды скомпилируйте в любом месте», никогда не портировал программу на C ++ ...
BlueRaja - Дэнни Пфлугхофт
7
Я согласен с BlueRaja. Портирование программы на C ++ означает гораздо больше, чем перенос компилятора. C ++ наиболее широко представлен в критических средах, где такие вещи, как размер int или реализация файловой системы могут иметь такое большое значение. Портирование НЕ просто означает перекомпиляцию.
раму
8
@ Pubby8 Нет, проблемы переносимости также возникают из-за довольно стандартного кода, который делает непереносимые предположения , такие как предположения о порядке байтов (который напоминает вам, вы также можете страдать в Java), выравнивание и размер фундаментальных типов.
Р. Мартиньо Фернандес
5
Пиши один раз, везде отлаживай.
Бхагьяс
25

«написание конкретной JRE для каждой платформы» - это не то, что вы делаете каждый раз. Портирование JRE на новую платформу - это то, что вам нужно сделать только один раз. Эта задача обычно выполняется основным сопровождающим / разработчиком программы и / или платформы. При принятии решения о том, кто и как будет переносить JRE, может влиять множество факторов. Помимо прочего, это зависит от лицензии, под которой она опубликована (я слышал, что Java - это Open Source, так что, думаю, кто-то может это сделать). Забавный анекдот, Стив Джобс много думал о том, что не хотел заботиться о портировании Java на Mac около года назад.

Дело не в том, как или кто портирует JRE, а в том, что после его портирования каждое Java-приложение теперь теоретически должно легко работать на новой машине. В этом смысле JRE формирует уровень абстракции, полностью скрывая машину, что позволяет легко переносить.

Однако реальность не всегда так хороша. Я не стану называть переносимость «мифом», но это правда, что она не так совершенна. Например, в Java есть пакет под названием, JNIкоторый позволяет отправлять собственные вызовы, обходя JRE, тем самым предотвращая идеальную бесперебойную переносимость, которую любители Java любят называть «Писать один раз, запускай везде».

Как упоминалось в комментариях, подход C ++ к переносимости отличается. С одной стороны, это скомпилированный язык, и эти двоичные файлы почти всегда зависят от платформы. Таким образом, исполняемые файлы c ++ никогда не будут переносимыми (в отличие от Java). С другой стороны, портирования компилятора иногда бывает достаточно. Сообщество обнаружило, что путем переноса компилятора, а также некоторых основных библиотек языка, исходные коды (а не двоичные файлы) могут быть переносимыми.

Тем не менее, C ++ широко используется в критически важных системах, таких как компиляторы, ядра, системы реального времени, встраиваемые системы ... В C ++ есть аспект «низкого уровня», который нельзя упускать из виду, говоря о переносимости.

rahmu
источник
4
Портативность не миф. Идеальная переносимость есть.
Малкольм
«Здесь Java сильно отличается от C ++, где каждое приложение« машинно-специфично »и не может быть перенесено без изменения кода». Это не правда, это зависит от зависимостей. Если вы используете только стандартную библиотеку и библиотеки с источниками, переносимыми на ваши цели, вы пишете код один раз и компилируете для каждой цели. Если вы кодируете что-то, что может быть перенесено без изменения кода в C ++, единственное, что вам может понадобиться изменить - это скрипты сборки. Это даже не правда во всех случаях.
Klaim
Давайте не будем забывать, что C ++ может использоваться как язык высокого и низкого уровня. Большая часть кода на C ++ используется в программах, где 32-битное int очень отличается от 64-битного int. Конечно, высокий уровень всегда будет переносимым. Но это далеко от обобщения C ++
rahmu
Я думаю, что вы, возможно, неправильно поняли то, что я говорю: вы можете написать правильный C ++ с int или любым стандартным типом, не заботясь о низкоуровневых вещах. Просто взгляните на библиотеки наддува, большинство из них - только высокоуровневый код, и это верно для многих проектов с открытым исходным кодом на C ++. Вы «можете» перейти на низкий уровень, и если вы это сделаете, вы также можете избежать какого-либо конкретного кода, пока вам не понадобится использовать специфичный для платформы API. Но если вам не нужно, тогда вы можете написать C ++, который работает везде. Зависимости от платформы можно избежать, и это часто встречается в коде библиотеки.
Klaim
Просто чтобы быть уверенным, что я ясен: я не говорю, что весь код C ++ является переносимым, я говорю, что как есть, ваше утверждение неверно. Возможно, вы захотите исправить это следующим образом: «Здесь Java сильно отличается от C ++, где каждое приложение« машинно-специфично »и не может быть перенесено без изменения кода или, если код действительно переносим и сборка Сценарии управляют новой целью без хотя бы одной компиляции. "
Klaim
14

Это не просто язык - это библиотеки.

И Java, и C ++ предоставляют кроссплатформенные библиотеки. Java предоставляет более богатый набор.

Энди Томас
источник
2
Java предоставляет более богатый набор по умолчанию. Те же библиотеки можно найти для C ++, они просто не являются частью стандартных библиотек, и вам просто нужно решить, какие из них использовать (что нетривиально, особенно если они не установлены).
Мартин Йорк,
Сравнение стандартных библиотек Java с универсальным набором библиотек для C ++ не совсем корректное сравнение. Java предоставляет более богатый набор, сравнивая ли вы стандартные библиотеки каждого из них, или вы сравниваете совокупность библиотек каждого из них.
Энди Томас
3
Определенно не согласен с этим. Все, что доступно в библиотеке Java, уже доступно для использования C ++ в некоторой библиотеке. Мне нравится тот факт, что в Java все это есть в одном месте, но сказать, что он богаче, просто неправда. Возможно, прилагательное, которое вы ищете, «более интегрировано»
Мартин Йорк,
1
+1 снова будет голосовать. Я думаю, что библиотеки - самый большой фактор в переносимости. Если вы работаете в C / C ++ и занимаетесь чем-то иным, кроме чистых вычислений, будут библиотеки (в частности, части системной библиотеки), которые радикально отличаются между Windows и Unix и слегка различаются между различными разновидностями Unix. Это делает портирование сложным. У Java в принципе такой проблемы нет.
Том Андерсон
1
@ Энди Томас-Крамер: я ничего не сравниваю (кажется, вы). Я говорю, что ваше утверждение неточно. Одним из преимуществ, которое имеет Java (и нам всем это нравится), являются все стандартные библиотеки в одном месте. Сказать, что они богаче, просто не правильно.
Мартин Йорк,
7

Разница в том, что Java будет работать на любой платформе без перекомпиляции. Наличие компилятора C ++ для каждой платформы совсем не одно и то же.

Хайленд Марк
источник
6

Все ответы, начинающиеся с «Разница в ...», или что-то очень похожее, в основном неверны (извините, но такова жизнь). Есть действительно два отдельных различия между ними.

Одна из них (о которой много говорилось) заключается в том, что скомпилированная Java-программа может (или, по меньшей мере, должна) работать на любой соответствующей реализации Java, поэтому даже после компиляции вы все равно можете перемещать Java-программу с одной платформы на другую без повторной компиляции. , C ++ (по крайней мере, обычно) требует повторной компиляции для каждой целевой платформы.

Другая заключается в том, что Java (по крайней мере, пытается) гарантировать, что вся правильно написанная Java будет переносимой. По крайней мере, теоретически, вы не должны быть в состоянии написать любой код, который не является переносимым.

C ++ позволяет вам делать довольно много вещей, которые не переносимы. Стандарт C ++ содержит «предупреждения» о многих вещах, которые не переносимы (например, сообщают вам, что вы получите поведение, определяемое реализацией, или поведение, не определенное), но он не обязательно пытается помешать вам сделать это вообще. , Например, если вы хотите написать операционную систему для оборудования, использующего шину PCI, вам, вероятно, понадобится чтение / запись памяти конфигурации PCI. Это, очевидно, не будет переносимым на системы без шины PCI, но если вы пишете операционную систему для оборудования с шиной PCI, это в значительной степени необходимо. C ++ позволяет это, хотя, очевидно, он не будет переносимым.

Джерри Гроб
источник
C ++ ничего не знает ни о шине PCI, ни о железе.
Никко
конечно, это не так, это специфичные для платформы вещи, которые должны быть включены в специфичные для платформы библиотеки. Так же, как Java может иметь специфичные для платформы библиотеки, если это необходимо.
С
1
@ Никко: Он ничего не знает об этом, но позволяет вам использовать то, что вы знаете об этом.
Джерри Коффин
@jwenting: Разница в том, что вы можете писать специфичные для платформы библиотеки на C ++, но, как правило, вы не можете писать их на Java.
Джерри Коффин
6

Вы неправильно поняли помещение. Java- программы очень переносимы, потому что JVM обеспечивает стандартное поведение, гарантирующее то же самое. Программы на C ++ имеют менее стандартизированную среду, более близкую к реальному аппаратному обеспечению, поэтому программа должна быть в состоянии обрабатывать различные специфичные для платформы детали, такие как размер типа int, выравнивание слов и т. Д. И т. Д. И т. Д.

Сама JVM не очень портативна. Это непростая задача - портировать высокопроизводительную JVM на другую платформу или архитектуру процессора.


источник
+1 за последнее предложение!
Рахму
2

Разница в том, что Java (это не аббревиатура) программы могут распространяться в форме, которая может быть запущена на любом компьютере с установленной JVM, но C ++ обычно распространяется либо как исходный код, который очень неудобен для пользователя, либо как группа разных бинарных файлов для разных платформ.

Colin
источник
А? Есть компиляторы C ++, предназначенные для JVM, и есть компиляторы Java, предназначенные для собственного кода. Можете ли вы привести конкретный раздел спецификации языка C ++, в котором говорится, что программы на C ++ должны распространяться либо в виде исходного кода, либо в виде двоичных файлов для конкретной платформы?
Йорг Миттаг
Там я отредактировал свой ответ, чтобы использовать менее определенный язык
Colin
2

Одна из причин, по которой Java считается переносимой, заключается в том, что в ней есть конкретные правила оценки арифметических выражений и запрещается реализациям оценивать их любым другим способом, даже если для оценки их в соответствии с предписаниями требуется более медленный код, чем при их более точной оценке. мода.

Например, учитывая

long thing1(int x) {
  return (x+1)-1L;
}
double thing2(int x, float y) {
  return x/y;
}

Значения thing1(2147483647)и thing2(1123456700,11234567.0f)должны быть равны -2147483649L и 99.9999923706054688, соответственно, даже если арифметически правильные значения будут 2147483647L и 100.0, и хотя на некоторых платформах код для генерирования численно-неверных результатов будет медленнее, чем код для генерации правильных результаты (на некоторых 64-битных платформах для принудительного переноса после (x + 1) потребуется дополнительная инструкция, а на платформе 8x87 для округления до значения 1123456700 floatпотребуется дополнительная инструкция по сравнению с простой загрузкой это непосредственно в регистр с расширенной точностью).

Supercat
источник
1
На этот раз новый ответ на старый вопрос, который действительно добавляет что-то ценное: Java предъявляет очень точные арифметические требования, и, конечно, примитивные типы данных имеют определенные размеры и семантику по сравнению с C ++. Никакой другой ответ на эту дату не упоминает об этом.
@ Снеговик: Как вам нравятся конкретные примеры? Лично если бы я разработка языка я не сделал бы ценность либо пример возвращение в Java без использования сужения забросов в (int)качестве первого примера в (x+1)подвыражения в первом примере, на floatвторой пример по xпараметру, но , очевидно , я не дизайну языка ,
суперкат
Я думаю, что они имеют смысл. Для любого языка важно иметь четкую семантику. Независимо от того, согласен ли кто-то с данным решением по проектированию языка, важно иметь возможность смотреть на код и знать, как он работает. Java обычно делает это, с несколькими случаями неопределенного поведения.
1

Объем работы для вспомогательных инструментов действительно одинаков, разница кроется в другом. После того, как программа C ++ была скомпилирована для платформы, вы должны скомпилировать ее снова, если хотите использовать ее на другой платформе. Однако, когда Java-программа была скомпилирована, вы можете переместить ее на любую другую платформу со средой выполнения без необходимости перекомпиляции.


источник
1

Отвечая на вопрос «Является ли переносимость мифом?» Вместо «Что лучше в переносимости, Java или C ++», я скажу, что частичная переносимость возможна, но полная переносимость - это миф.

То, что я настаиваю на написании, и это относится к этому вопросу, заключается в том, что разработчики больше не работают только с простыми языками программирования, а с полными средами программирования.

И эти структуры включают библиотеки, базы данных, графические интерфейсы.

Какой язык программирования или какая среда программирования более переносимая?

Ну, это зависит от того, что ваше приложение. пытается достичь.

umlcat
источник
1

Дело в том, что «вы» не пишете JRE, вы пишете код Java, который выполняется на любом JRE. «Вы» пишете код C ++, который может потребовать внесения вами изменений, прежде чем он скомпилируется на другой платформе.

Джеймс Андерсон
источник
0

Многие люди забывают или не принимают во внимание реальность Java, когда говорят, что «она на 100% портативна» или подобные фразы.

Практически во всех крупных корпорациях / отделе программного обеспечения в недавнем прошлом была как минимум одна самодельная реализация Java со связанной с ней JRE, и некоторые до сих пор ее поддерживают, например, у Microsoft, IBM и Apple была своя собственная версия Java, отражающая их собственные идеи и мысли о том, куда должна идти индустрия и такой язык.

Как это для "портативного"? JRE везде, где вы включаете.

И это без учета того, что делал Sun / Oracle.

Примером того, почему Java-код не очень далек от C и C ++ с точки зрения переносимости, являются графические интерфейсы и графические серверы, у Apple была нестандартная реализация структуры графического интерфейса для собственного JRE, в результате чего было много головные боли и двойная работа для тех, кто хотел создать / перенести GUI с использованием Java для компьютеров Apple, и они были в основном вынуждены иметь дело с Quartz (как это с точки зрения «рычагов» и языков высокого уровня?).

Иногда даже наиболее часто используемые слова не отражают того значения, которое обычно им дают люди, для меня термин «переносимость» в мире Java больше похож на «внешний вид» в общем смысле; в коммерческом и финансовом плане перспективы лучше для вас , если вы принимаете Java , а не на других языках (по крайней мере , в то время , когда Java родился) , потому что у вас есть много работы , уже проделанной на одной стороне (вы получите JRE на что - либо это можно считать «компьютером»), и ваша кодовая база, вероятно, будет переносимой, поскольку вам нужно меньше ресурсов для переноса вашей программы, вот и все, независимо от того, является ли указанный ресурс деньгами, время или трудовые ресурсы не имеют значения, это меньше порог по сравнению с другими технологиями, и это то, для чего Java, это снижает этот порог.

Конечно, это верно, если вы принимаете условия Java, что означает виртуальную машину со сборкой мусора, что означает, что она потребляет больше ресурсов по сравнению с родными языками, если вы действительно хотите выжать максимум из вашего ЦП или серверной фермы. не думайте, что вы можете принять Java, если у вас действительно мало ресурсов или ваша компания действительно мала.

Мне все еще нужно найти одно нетривиальное Java-приложение, которое содержит только 1 версию для каждой строки кода или функциональности (то есть без какой-либо платформы), и оно на 100% переносимо среди всех основных JRE.

user2485710
источник