Dlaczego Java jest uważana za bardziej przenośną niż inne języki, takie jak C ++?

16

Co różni się między „pisaniem konkretnego środowiska JRE dla każdej platformy” dla programistów Java a „pisaniem kompilatora C ++ dla każdej platformy” dla programistów C ++?

użytkownik967316
źródło

Odpowiedzi:

33

Java jest kompilowana po uruchomieniu w dowolnym miejscu. C ++ jest napisany po kompilacji w dowolnym miejscu.

Pubby
źródło
3
Oczywiście nie masz dużego doświadczenia w tworzeniu GUI. (Oczekiwanie na Qt ...)
27
Każdy, kto twierdzi, że C ++ „pisze raz kompiluj gdziekolwiek” nigdy nie musiał
przenosić
7
Zgadzam się z BlueRaja. Przeniesienie programu C ++ oznacza o wiele więcej niż przeniesienie kompilatora. C ++ jest najszerzej obecny w środowiskach krytycznych, w których wielkość int lub implementacja systemu plików może mieć tak dużą różnicę. Przenoszenie NIE oznacza po prostu ponownej kompilacji.
rahmu
8
@ Pubby8 nie, problemy związane z przenośnością wynikają również z dość standardowego kodu, który przyjmuje niezbywalne założenia , takie jak założenia dotyczące endianizmu (które mają na ciebie negatywny wpływ w Javie), wyrównania i rozmiaru podstawowych typów.
R. Martinho Fernandes
5
Napisz raz, debuguj wszędzie.
bhagyas
25

„pisanie konkretnego środowiska JRE dla każdej platformy” nie jest czymś, co robisz za każdym razem. Przeniesienie środowiska JRE na nową platformę to czynność, którą należy wykonać tylko raz. To zadanie jest na ogół wykonywane przez głównego opiekuna / programistów programu i / lub platformy. Przy podejmowaniu decyzji, kto i jak zostanie przeniesione środowisko JRE, może mieć wpływ wiele czynników. Między innymi zależy to od licencji, pod którą jest publikowany (słyszę, że Java to Open Source, więc chyba każdy mógłby to zrobić). Śmieszna anegdota, Steve Jobs zrobił wiele o tym , że około roku temu nie chciał zająć się przenoszeniem Java na Maca .

Nie chodzi o to, jak i kto przenosi środowisko JRE, ale o fakt, że po jego przeniesieniu każda aplikacja Java powinna teoretycznie łatwo działać na nowej maszynie. W tym sensie środowisko JRE tworzy warstwę abstrakcji, całkowicie ukrywając maszynę, umożliwiając łatwe przenoszenie.

Jednak rzeczywistość nie zawsze jest taka ładna. Nie posunę się tak daleko, nazywając przenośność „mitem”, ale prawdą jest, że nie jest ona tak idealna. Na przykład Java ma pakiet o nazwie, JNIktóry umożliwia wysyłanie wywołań natywnych, z pominięciem środowiska JRE, co uniemożliwia idealną bezproblemową przenośność, którą fani Java lubią nazywać „Napisz wszędzie uruchamiane”.

Jak wspomniano w komentarzach, podejście C ++ do przenośności jest inne. Z jednej strony jest to skompilowany język, a te pliki binarne prawie zawsze są specyficzne dla platformy. Pliki wykonywalne c ++ nigdy nie będą przenośne (w przeciwieństwie do Java). Z drugiej strony, portowanie kompilatora może czasem wystarczyć. Społeczność odkryła, że ​​przez przeniesienie kompilatora, a także niektórych podstawowych bibliotek języka, kody źródłowe (a nie pliki binarne) mogą być przenośne.

Jednak C ++ jest szeroko stosowany w systemach krytycznych, takich jak kompilatory, jądra, systemy czasu rzeczywistego, systemy osadzone ... Istnieje aspekt „niskiego poziomu” C ++, którego nie można przeoczyć, mówiąc o przenośności.

rahmu
źródło
4
Przenośność nie jest mitem. Idealna przenośność to.
Malcolm,
„W tym przypadku Java różni się bardzo od C ++, gdzie każda aplikacja jest„ specyficzna dla maszyny ”i nie można jej przenieść bez modyfikacji kodu.” To nie prawda, to zależy od zależności. Jeśli używasz tylko standardowej biblioteki i bibliotek ze źródłami przenośnymi dla swoich celów, kodujesz raz i kompilujesz dla każdego celu. Jeśli kodujesz coś, co można przenieść bez modyfikowania kodu w C ++, jedyną rzeczą, którą musisz zmodyfikować, są skrypty kompilacji. To nie jest nawet prawda we wszystkich przypadkach.
Klaim
Nie zapominajmy, że C ++ może być używany zarówno jako język wysokiego, jak i niskiego poziomu. Dużo kodu C ++ jest używane w programach, w których 32-bitowy int różni się bardzo od 64-bitowego int. Oczywiście wysoki poziom zawsze będzie przenośny. Ale daleko mu do uogólnienia w C ++
rahmu
Myślę, że mogłeś źle zrozumieć to, co mówię: możesz pisać poprawne C ++ za pomocą int lub dowolnego standardowego typu bez zawracania sobie głowy sprawami niskiego poziomu. Wystarczy spojrzeć na biblioteki boost, większość z nich to tylko kod wysokiego poziomu, i tak jest w przypadku wielu projektów open source C ++. Możesz „przejść” na niski poziom, a jeśli to zrobisz, możesz także uniknąć określonego kodu, dopóki nie będziesz musiał używać interfejsu API specyficznego dla platformy. Ale jeśli nie musisz, możesz napisać C ++, który działa wszędzie. Zależności od platformy można uniknąć i często występuje ona w kodzie biblioteki.
Klaim
Żeby się upewnić, nie mam wątpliwości: nie mówię, że cały kod C ++ jest przenośny, mówię, że twoje zdanie jest błędne. Możesz to naprawić za pomocą: „W tym przypadku Java różni się bardzo od C ++, gdzie każda aplikacja jest„ specyficzna dla maszyny ”i nie można jej przenieść bez modyfikacji kodu lub, jeśli kod jest naprawdę przenośny i kompilacja skrypty zarządzają nowym celem, bez co najmniej jednej kompilacji. ”
Klaim
14

To nie tylko język - to biblioteki.

Zarówno Java, jak i C ++ zapewniają biblioteki wieloplatformowe. Java zapewnia bogatszy zestaw.

Andy Thomas
źródło
2
Domyślnie Java zapewnia bogatszy zestaw. Te same biblioteki można znaleźć w C ++, po prostu nie są one częścią bibliotek standardowych i po prostu musisz zdecydować, których z nich użyć (co nie jest trywialne, zwłaszcza jeśli nie są zainstalowane).
Martin York,
Porównanie standardowych bibliotek Java z uniwersum bibliotek dla C ++ nie jest tak naprawdę poprawnym porównaniem. Java zapewnia bogatszy zestaw, niezależnie od tego, czy porównujesz standardowe biblioteki każdej z nich, czy porównujesz wszechświat bibliotek każdej z nich.
Andy Thomas
3
Zdecydowanie się z tym nie zgadzam. Wszystko w bibliotece Java jest już dostępne do użycia przez C ++ w niektórych bibliotekach. Podoba mi się fakt, że Java ma to wszystko w jednym miejscu, ale stwierdzenie, że jest bogatszy, po prostu nie jest prawdą. Może przymiotnik, którego szukasz, jest `` bardziej zintegrowany ''
Martin York,
1
+1 ponownie zagłosuje. Myślę, że biblioteki są największym czynnikiem w przenośności. Jeśli pracujesz w C / C ++ i robisz cokolwiek innego niż czyste obliczenia, pojawią się biblioteki (w szczególności części biblioteki systemowej), które są radykalnie różne dla Windows i Unixa i nieznacznie różnią się między różnymi smakami Uniksa. To utrudnia portowanie. Java zasadniczo nie ma tego problemu.
Tom Anderson
1
@Andy Thomas-Cramer: Nic nie porównuję (wydajesz się być). Mówię, że twoje oświadczenie jest niedokładne. Jedną z zalet Java (i wszyscy to uwielbiamy) są wszystkie standardowe biblioteki w jednym miejscu. Mówienie, że są bogatsze, po prostu nie jest dokładne.
Martin York,
7

Różnica polega na tym, że Java będzie działać na dowolnej platformie bez ponownej kompilacji. Posiadanie kompilatora C ++ dla każdej platformy wcale nie jest takie samo.

Highland Mark
źródło
6

Wszystkie odpowiedzi zaczynające się od „Różnica jest…” lub coś bardzo podobnego, są zasadniczo błędne (przepraszam, ale takie jest życie). Istnieją naprawdę dwie odrębne różnice między nimi.

Jedną (o której często wspomniano) jest to, że skompilowany program Java może (lub przynajmniej powinien) działać na dowolnej zgodnej implementacji Java, więc nawet po skompilowaniu nadal możesz przenosić program Java z jednej platformy na drugą bez ponownej kompilacji . C ++ (przynajmniej normalnie) wymaga ponownej kompilacji dla każdej platformy docelowej.

Po drugie, Java (przynajmniej próbuje) zapewnić, że wszystkie poprawnie napisane Java będą przenośne. Przynajmniej teoretycznie nie powinieneś być w stanie napisać żadnego kodu, który nie jest przenośny.

C ++ pozwala ci robić kilka rzeczy, które nie są przenośne. Standard C ++ zawiera „ostrzeżenia” o wielu rzeczach, które nie są przenośne (np. Informujące o tym, że otrzymasz zachowanie zdefiniowane w implementacji lub zachowanie nieokreślone), ale niekoniecznie próbuje Cię powstrzymać . Na przykład, jeśli chcesz napisać system operacyjny dla sprzętu korzystającego z magistrali PCI, prawdopodobnie będziesz musiał odczytać / zapisać pamięć konfiguracji PCI. To oczywiście nie będzie przenośne dla systemów bez magistrali PCI, ale jeśli piszesz system operacyjny dla sprzętu z magistralą PCI, jest to prawie konieczne. C ++ pozwala na to, nawet jeśli oczywiście nie będzie przenośny.

Jerry Coffin
źródło
C ++ nie wie jednak nic o magistrali PCI ani sprzęcie.
Nikko
oczywiście, że nie, są to rzeczy specyficzne dla platformy, które będą musiały zostać uwzględnione w bibliotekach specyficznych dla platformy. Podobnie jak Java może w razie potrzeby mieć biblioteki specyficzne dla platformy.
jwenting
1
@Nikko: Nic o tym nie wie, ale pozwala ci wykorzystać to , co o nim wiesz.
Jerry Coffin
@jwenting: Różnica polega na tym, że możesz pisać biblioteki specyficzne dla platformy w C ++, ale generalnie nie możesz pisać ich w Javie.
Jerry Coffin
6

Źle zrozumiałeś przesłankę. Programy Java są bardzo przenośne, ponieważ JVM zapewnia standardowe zachowanie, które jest takie samo. Programy C ++ mają mniej znormalizowane środowisko bliższe rzeczywistemu sprzętowi, więc program musi być w stanie obsłużyć różne szczegóły specyficzne dla platformy - takie jak rozmiar int, wyrównanie słów itp. Itp.

Sam JVM nie jest zbyt przenośny. Herkulesowym zadaniem jest przeniesienie wysokowydajnej maszyny JVM na inną platformę lub architekturę procesora.


źródło
+1 za ostatnie zdanie!
rahmu
2

Różnica polega na tym, że programy Java (to nie skrót) mogą być dystrybuowane w formie, którą można uruchomić na dowolnym komputerze z zainstalowaną maszyną JVM, ale C ++ jest zwykle dystrybuowany jako dowolny kod źródłowy, który jest bardzo nieprzyjazny dla użytkownika, lub jako grupa różnych plików binarnych dla różnych platform.

Colin
źródło
Co? Istnieją kompilatory C ++, które są ukierunkowane na JVM, i są kompilatory Java, które są ukierunkowane na kod macierzysty. Czy możesz przytoczyć konkretną sekcję specyfikacji języka C ++, która mówi, że programy C ++ muszą być rozpowszechniane jako kod źródłowy lub pliki binarne specyficzne dla platformy?
Jörg W Mittag
Tam zredagowałem moją odpowiedź, aby użyć mniej jednoznacznego języka
Colin,
2

Jednym z powodów, dla których Java jest uważana za przenośną, jest to, że ma określone zasady dotyczące wyceny wyrażeń arytmetycznych i zabrania implementacjom ich oceniania w jakikolwiek inny sposób, nawet jeśli ocena ich w mandat wymagałaby wolniejszego kodu niż ocena ich w bardziej dokładny sposób moda.

Na przykład dane

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

Wartości thing1(2147483647)i thing2(1123456700,11234567.0f)muszą wynosić odpowiednio -2147483649L i 99.9999923706054688, mimo że poprawne arytmetycznie byłyby 2147483647L i 100,0, a nawet jeśli na niektórych platformach kod do wygenerowania niepoprawnych liczbowo wyników byłby wolniejszy niż kod do wygenerowania poprawnych wyniki (na niektórych platformach 64-bitowych wymuszenie zachowania zawijania po (x + 1) wymagałoby dodatkowej instrukcji, a na platformie 8x87 wymuszenie zaokrąglenia wartości 1123456700 do floatdodatkowej instrukcji w porównaniu z zwykłym ładowaniem bezpośrednio do rejestru o rozszerzonej precyzji).

supercat
źródło
1
Po raz kolejny nowa odpowiedź na stare pytanie, które w rzeczywistości dodaje coś wartościowego: Java ma bardzo precyzyjne wymagania arytmetyczne, a pierwotne typy danych mają określone rozmiary i semantykę w porównaniu do C ++. Żadna inna odpowiedź na ten dzień nie wspomina o tym.
@Snowman: Jak ci się podobają wybrane przykłady? Osobiście, gdybym projektował język, nie sprawiłbym, że którykolwiek z przykładów zwróciłby wartość Java bez użycia rzutów zwężających się (int)do (x+1)podwyrażenia pierwszego przykładu w pierwszym przykładzie, do floatparametru drugiego przykładu x, ale oczywiście nie zaprojektowałem tego języka .
supercat,
Myślę, że mają sens. Dla każdego języka ważne jest, aby mieć dobrze zdefiniowaną semantykę. Niezależnie od tego, czy ktoś zgadza się z daną decyzją dotyczącą projektu języka, ważne jest, aby spojrzeć na kod i wiedzieć, jak on działa. Java ogólnie to robi, z kilkoma przypadkami niezdefiniowanego zachowania.
1

Ilość pracy dla narzędzi pomocniczych jest rzeczywiście podobna, różnica leży gdzie indziej. Po skompilowaniu programu C ++ dla platformy musisz go skompilować ponownie, jeśli chcesz go używać na innej platformie. Jednak po skompilowaniu programu Java można przenieść go na dowolną platformę ze środowiskiem wykonawczym bez konieczności jego ponownej kompilacji.


źródło
1

Odpowiadając na tytuł „Czy przenośność to mit?”, Zamiast „Który lepszy jest w przenośności, Javie lub C ++”, powiem, że częściowa przenośność jest możliwa, ale pełna przenośność to mit.

Coś, co nalegam na napisanie i dotyczy to tego pytania, polega na tym, że programiści nie pracują już tylko z językami programowania, ale z pełnymi ramami programistycznymi.

A te frameworki obejmują biblioteki, bazy danych, interfejsy graficzne.

Który język programowania lub która struktura programowania jest bardziej przenośna?

To zależy od tego, co twoja aplikacja. próbuje osiągnąć.

umlcat
źródło
1

Chodzi o to, że „ty” nie piszesz środowiska JRE, piszesz kod Java, który działa na dowolnym środowisku JRE. „Ty” piszesz kod C ++, który może wymagać zmian , zanim skompiluje się na innej platformie.

James Anderson
źródło
0

Wiele osób zapomina lub nie bierze pod uwagę rzeczywistości Java, mówiąc, że „jest w 100% przenośny” lub podobnych zwrotów.

Prawie wszystkie duże korporacje / Software house miały w ostatnim czasie co najmniej 1 domową implementację Java ze skojarzonym JRE, a niektóre nadal ją utrzymują, na przykład Microsoft, IBM i Apple miały swoją własną wersję Java odzwierciedlającą ich własne pomysły i przemyślenia na temat tego, gdzie powinna iść branża i taki język.

Jak to jest w przypadku „przenośnego”? JRE gdziekolwiek się obrócisz.

I to bez uwzględnienia tego, co robi Sun / Oracle.

Przykładem tego, dlaczego kod Java nie jest tak daleki od C i C ++ pod względem przenośności, są GUI i serwery graficzne, Apple miał niestandardową implementację frameworku GUI dla własnego środowiska JRE, w wyniku czego wiele bóle głowy i podwójna praca dla każdego, kto chciał stworzyć / przenieść GUI za pomocą Java na maszyny Apple i byli w zasadzie zmuszeni do radzenia sobie z Quartzem (jak to się ma w przypadku „dźwigni” i języków wysokiego poziomu?).

Czasami nawet najczęściej używane słowa nie odzwierciedlają znaczenia, które ludzie zwykle im nadają, dla mnie termin „przenośność” w świecie Java przypomina bardziej „perspektywę” w zdrowym znaczeniu; pod względem handlowym i finansowym jest lepsza perspektywa , jeśli zastosujesz Javę zamiast innych języków (przynajmniej w momencie narodzin Java), ponieważ masz już dużo pracy po jednej stronie (dostajesz JRE na wszystko które można uznać za „komputer”), a twoja baza kodów prawdopodobnie będzie przenośna, potrzebujesz mniej zasobów do przeniesienia programu, to wszystko, czy wspomniane zasoby to pieniądze, czas lub siła robocza nie ma znaczenia, jest to niższe próg w porównaniu do innych technologii i po to jest Java, obniża ten próg.

Oczywiście jest to prawdą, jeśli zaakceptujesz założenia Javy, co oznacza maszynę wirtualną z funkcją wyrzucania elementów bezużytecznych, co oznacza, że ​​zużywa ona więcej zasobów w porównaniu z językami ojczystymi, jeśli naprawdę chcesz wycisnąć maksimum z procesora lub farmy serwerów I nie myśl, że możesz adoptować Javę, chyba że masz bardzo mało zasobów lub Twoja firma jest naprawdę mała.

Nadal muszę znaleźć jedną nietrywialną aplikację Java, która zawiera tylko 1 wersję dla każdego wiersza kodu lub funkcjonalności (czyli bez żadnych specyficznych dla platformy rzeczy) i jest w 100% przenośna wśród wszystkich głównych środowisk JRE.

użytkownik2485710
źródło