Kritik af Java - Criticism of Java
Den programmeringssproget Java og Java-software platform er blevet kritiseret for designvalg, herunder implementeringen af generiske lægemidler, tvungen objektorienteret programmering, håndtering af usigneret tal, gennemførelsen af floating-point aritmetik, og en historie af sikkerhedshuller i den primære Java VM -implementering, HotSpot . Software skrevet i Java, især dens tidlige versioner, er blevet kritiseret for sin ydeevne sammenlignet med software skrevet på andre programmeringssprog. Udviklere har også bemærket, at forskelle i forskellige Java -implementeringer skal tages i betragtning, når man skriver komplekse Java -programmer, der skal fungere med dem alle.
Sprogsyntaks og semantik
Generics
Da generikere blev tilføjet til Java 5.0, var der allerede en stor ramme af klasser (hvoraf mange allerede var udfaset ), så generika blev implementeret ved hjælp af sletning af typer for at muliggøre migrationskompatibilitet og genbrug af disse eksisterende klasser. Dette begrænsede de funktioner, der kunne leveres, sammenlignet med andre sprog.
Fordi generika implementeres ved hjælp af sletning af typen, er den faktiske type af en skabelonparameter E ikke tilgængelig på kørselstidspunktet. Følgende operationer er således ikke mulige i Java:
public class MyClass<E> {
public static void myMethod(Object item) {
if (item instanceof E) { //Compiler error
...
}
E item2 = new E(); //Compiler error
E[] iArray = new E[10]; //Compiler error
}
}
Substantivorienteret
Ved design tilskynder Java programmører til at tænke på en løsning i form af substantiver (klasser), der interagerer med hinanden, og til at tænke på verber (metoder) som operationer, der kan udføres på eller ved det navneord. Steve Yegge hævder, at dette medfører en unødvendig begrænsning af sprogets udtryksfuldhed, fordi en klasse kan have flere funktioner, der fungerer på den, men en funktion er bundet til en klasse og kan aldrig fungere på flere typer.
Mange andre multi-paradigmasprog understøtter funktioner som en konstruktion på topniveau. Når den kombineres med andre funktioner såsom funktionsoverbelastning (ét verb, flere substantiver) og generiske funktioner (ét verbum, en familie af navneord med bestemte egenskaber), kan programmøren beslutte, om et bestemt problem skal løses i form af substantiver eller verber. Java version 8 introducerede nogle funktionelle programmeringsfunktioner.
Skjult forhold mellem kode og hardware
I 2008 offentliggjorde det amerikanske forsvarsministeriums Center Software Technology Support en artikel i "Journal of Defense Software Engineering", der diskuterede uegnetheden af Java som det første sprog, der undervises i. Ulemper var, at eleverne "ikke havde nogen fornemmelse af forholdet mellem kildeprogrammet og hvad hardwaren rent faktisk ville gøre" og umuligheden "for at udvikle en fornemmelse af driftstidens omkostninger ved det, der er skrevet, fordi det er ekstremt svært at vide, hvad nogen metodeopkald vil i sidste ende blive udført ". I 2005 kritiserede Joel Spolsky Java som en overfokuseret del af universiteternes læseplaner i sit essay The Perils of JavaSchools . Andre, som Ned Batchelder, er uenige med Spolsky for at kritisere de dele af sproget, som han havde svært ved at forstå, og hævdede, at Spolskys kommentar mere var en 'subjektiv rant'.
Usignerede heltalstyper
Java mangler oprindelige usignerede heltalstyper . Usignerede data genereres ofte fra programmer skrevet i C , og manglen på disse typer forhindrer direkte dataudveksling mellem C og Java. Usignerede store tal bruges også i en række numeriske behandlingsfelter, herunder kryptografi, hvilket kan gøre Java mere ubelejligt at bruge til disse opgaver. Selvom det er muligt at komme udenom dette problem ved hjælp af konverteringskode og større datatyper, gør det brug af Java besværligt til håndtering af usignerede data. Mens et 32-bit signeret heltal kan bruges til at holde et 16-bit usigneret værdi tabsfrit, og et 64-bit signeret helt tal et 32-bit usigneret heltal, er der ingen større type til at holde et 64-bit usigneret helt tal. I alle tilfælde kan den forbrugte hukommelse fordobles, og typisk skal enhver logik, der er afhængig af to komplementoverløb, omskrives. Hvis det abstraheres, bliver funktionsopkald nødvendige for mange operationer, der er native til nogle andre sprog. Alternativt er det muligt at bruge Javas signerede heltal til at efterligne usignerede heltal af samme størrelse, men dette kræver detaljeret viden om bitvise operationer . Nogle understøttelser for usignerede heltals typer blev leveret i JDK 8, men ikke for usignerede bytes og uden understøttelse af Java -sproget.
Operatør overbelastning
Java er blevet kritiseret for ikke at understøtte brugerdefinerede operatører. Overbelastning af operatører forbedrer læsbarheden, så dens fravær kan gøre Java -kode mindre læsbar, især for klasser, der repræsenterer matematiske objekter, såsom komplekse tal og matricer. Java har kun en ikke-numerisk brug af en operator: +til streng sammenkædning. Men dette implementeres af kompilatoren, som genererer kode til at oprette StringBuilder-forekomster-det er umuligt at oprette brugerdefinerede overbelastninger af operatører.
Sammensatte værdityper
Java mangler sammensatte værdityper, såsom strukturer i C, bundter af data, der manipuleres direkte i stedet for indirekte via referencer. Værdityper kan nogle gange være hurtigere og mindre end klasser med referencer. For eksempel er Java's HashMapimplementeret som en række referencer til HashMap.Entryobjekter, som igen indeholder referencer til nøgle- og værdiobjekter. At se noget op kræver ineffektiv dobbelt dereferencing. Hvis det Entryvar en værditype, kunne arrayet lagre nøgle-værdipar direkte, hvilket eliminerede den første indirektion, øgede lokalitet for reference og reducerede hukommelsesbrug og bunkefragmentering . Yderligere, hvis Java understøttede generiske primitive typer, kunne nøgler og værdier gemmes direkte i arrayet, hvilket fjernede begge niveauer af indirektion.
Store arrays
Java er blevet kritiseret for ikke at understøtte arrays med 2 31 (ca. 2,1 mia.) Eller flere elementer. Dette er en begrænsning af sproget; den Java Language Specification , § 10.4, hedder det:
Arrays skal indekseres med int-værdier ... Et forsøg på at få adgang til en array-komponent med en lang indeksværdi resulterer i en kompileringstidsfejl.
Understøttelse af store arrays ville også kræve ændringer af JVM. Denne begrænsning manifesterer sig på områder som samlinger, der er begrænset til 2 milliarder elementer, og manglende evne til at hukommelseskort kontinuerlige filsegmenter større end 2 GB. Java mangler også flerdimensionale arrays (sammenhængende tildelte enkelte hukommelsesblokke, som en enkelt indirektion får adgang til), hvilket begrænser ydeevnen for videnskabelig og teknisk computing.
Der er ingen effektiv måde at initialisere arrays i Java. Når deklarerer et array, kompilerer JVM det til bytecodes med instruktioner, der sætter dets elementer en efter en ved løbetid. Fordi Java -metoder ikke kan være større end 64KB, vil arrays af selv beskedne størrelser med værdier, der er tildelt direkte i koden, sende meddelelsen "Fejl: kode for stor" på kompilering.
Integration af primitiver og arrays
Arrays og primitiver er noget specielle og skal behandles anderledes end klasser. Dette er blevet kritiseret, fordi det kræver mange varianter af funktioner, når man opretter generelle biblioteker.
Parallelisme
Per Brinch Hansen hævdede i 1999, at Java's implementering af parallelisme generelt og især monitorer ikke giver de garantier og håndhævelser, der kræves for sikker og pålidelig parallelprogrammering. Mens en programmør kan etablere design og kodning konventioner , kan compileren gør intet forsøg på at håndhæve dem, så programmøren uforvarende kan skrive usikker eller upålidelig kode.
Serialisering
Java leverer en mekanisme kaldet objektserialisering, hvor et objekt kan repræsenteres som en sekvens af bytes, der indeholder dets datafelter, sammen med typeoplysninger om sig selv og dets felter. Efter at et objekt er serieliseret objekt, kan det senere deserialiseres; det vil sige, at typeoplysninger og bytes, der repræsenterer dens data, kan bruges til at genskabe objektet i hukommelsen. Dette medfører meget alvorlige teoretiske og faktiske sikkerhedsrisici.
Flydende aritmetik
Selvom Java's flydende aritmetik stort set er baseret på IEEE 754 ( Standard for Binary Floating-Point Arithmetic ), understøttes nogle mandatstandardfunktioner ikke, selv når du bruger strictfpmodifikatoren, f.eks. Undtagelsesflag og dirigerede afrundinger. De udvidede præcisionstyper defineret af IEEE 754 (og understøttet af mange processorer) understøttes ikke af Java.
Ydeevne
Før 2000, da HotSpot VM blev implementeret i Java 1.3, var der meget kritik af dens ydeevne. Java har vist sig at køre med en hastighed, der kan sammenlignes med optimeret native -kode, og moderne JVM -implementeringer benchmarkes regelmæssigt som en af de hurtigste tilgængelige sprogplatforme - typisk ikke mere end tre gange langsommere end C og C ++.
Ydeevnen er forbedret betydeligt siden tidlige versioner. Ydeevne for JIT -kompilatorer i forhold til native compilers har vist sig at være ret ens i nogle optimerede test.
Java bytecode kan enten tolkes ved kørselstid af en virtuel maskine eller kompileres ved indlæsningstid eller kørselstid i native kode, der kører direkte på computerens hardware. Fortolkning er langsommere end indfødt udførelse, men kompilering ved indlæsningstid eller løbetid har en indledende præstationsstraf. Moderne JVM -implementeringer bruger alle kompilationsmetoden, så efter den første opstartstid ligner ydelsen den oprindelige kode.
Spildesigner og programmør John D. Carmack konkluderede i 2005 om Java på mobiltelefoner : "Det største problem er, at Java er virkelig langsom. På et rent cpu / hukommelse / display / kommunikationsniveau burde de fleste moderne mobiltelefoner være betydeligt bedre spil platforme end en Game Boy Advance. Med Java står du på de fleste telefoner tilbage med omtrent CPU -effekten på en original 4,77 mhz (sic) IBM PC og elendig kontrol over alt. "
Sikkerhed
Java -platformen giver en sikkerhedsarkitektur, der er designet til at give brugeren mulighed for at køre upålidelig bytecode på en "sandkasse" måde for at beskytte mod ondsindet eller dårligt skrevet software. Denne "sandboxing" -funktion er beregnet til at beskytte brugeren ved at begrænse adgangen til platformfunktioner og API'er, der kan udnyttes af malware , f.eks. Adgang til det lokale filsystem eller netværk, eller ved at køre vilkårlige kommandoer.
I 2010 var der en betydelig stigning i ondsindet software målrettet mod sikkerhedsfejl i sandboxing -mekanismerne, der bruges af Java -implementeringer, herunder Oracle's. Disse fejl tillader ikke -betroet kode at omgå sandkassebegrænsningerne og udsætte brugeren for angreb. Fejl blev rettet ved sikkerhedsopdateringer, men blev stadig udnyttet på maskiner uden opdateringerne.
Kritikere har foreslået, at brugerne ikke opdaterer deres Java -installationer, fordi de ikke ved, at de har dem, eller hvordan de opdaterer dem. Mange organisationer begrænser softwareinstallation af brugere, men er langsomme med at implementere opdateringer.
Oracle er blevet kritiseret for ikke straks at levere opdateringer til kendte sikkerhedsfejl. Da Oracle endelig frigav en patch til vidt udnyttede fejl i Java 7, fjernede den Java 6 fra brugernes maskiner, på trods af at den blev brugt i vid udstrækning af virksomhedsprogrammer, som Oracle havde oplyst ikke var påvirket af manglerne.
I 2007 afslørede et forskerhold ledet af Marco Pistoia en anden vigtig fejl ved Java -sikkerhedsmodellen baseret på stakinspektion . Når der tilgås en sikkerhedsfølsom ressource, udløser sikkerhedsadministratoren kode, der går i opkaldsstakken, for at kontrollere, at kodebasen for hver metode på den har autorisation til at få adgang til ressourcen. Dette gøres for at forhindre forvirrede stedfortrædende angreb , der finder sted hver gang et legitimt, mere privilegeret program bliver narret af en anden til at misbruge sin autoritet. Problemet med forvirret stedfortræder er en bestemt type privilegium-eskalering . Pistoia bemærkede, at når der er adgang til en sikkerhedsfølsom ressource, er koden, der er ansvarlig for at erhverve ressourcen, muligvis ikke længere på stakken. For eksempel kan en metode, der tidligere blev udført, have ændret værdien af et objektfelt, der bestemmer, hvilken ressource der skal bruges. Denne metodeopkald er muligvis ikke længere på stakken, når den inspiceres.
Nogle tilladelser svarer implicit til Java's AllPermission. Disse inkluderer tilladelse til at ændre den nuværende sikkerhedsmanager (og erstatte den med en, der muligvis kan omgå stakinspektionen), tilladelsen til at instantiere og bruge en brugerdefineret klasselæsser (som kunne vælge at knytte AllPermissionen ondsindet klasse til at indlæse den), og tilladelsen til at oprette en brugerdefineret tilladelse (som kunne erklære sig selv så magtfuld som AllPermissionvia dens impliesmetode). Disse spørgsmål er dokumenteret i Pistoias to bøger om Java Security: Java 2 Network Security (anden udgave) og Enterprise Java Security .
Parallelle installationer
Før Java 7 var det normalt, at installationsprogrammet ikke opdagede eller fjernede ældre Java -installationer. Det var ret almindeligt på en Windows -computer at se flere installationer af Java 6 på den samme computer, kun varierende ved mindre revision. Flere installationer er tilladt og kan bruges af programmer, der er afhængige af specifikke versioner.
Dette har den effekt, at nye Java -installationer kan levere nye sprogfunktioner og fejlrettelser, men de korrigerer ikke sikkerhedssårbarheder, fordi ondsindede programmer kan bruge de ældre versioner.
Java 7 opdaterede ældre versioner af sig selv, men ikke Java 6 eller tidligere.
Automatiske opdateringer
Fra 2014 har almindelige tredjepartsværktøjer (f.eks. Adobe Flash og Adobe Reader) været genstand for kontrol af sikkerhedsrisici. Adobe og andre er flyttet til automatiske opdateringer på Windows. Disse behøver ikke nogen brugerhandling og sikrer, at sikkerhedsproblemer hurtigt løses med minimal indsats af brugere eller administratorer.
Fra 2015 kræver Java 8 stadig, at brugerne selv skal opdatere Java. Men i Windows kan kun dem med administratorrettigheder opdatere software. Opdateringsprogrammet til Windows Java udløser ofte en forstyrrende prompt for brugerkontokontrol: uanset hvad brugerne vælger, får de stadig den samme "Java skal opdateres" -meddelelse.
Se også
- Sammenligning af Java og C ++
- Sammenligning af Java og C#
- Sammenligning af Java- og .NET -platformene
- Java ydeevne
- Skriv en gang, kør hvor som helst
Noter
eksterne links
- Free But Shackled - The Java Trap , et essay af Richard Stallman om fri software -bevægelse (dateret 12. april 2004)
- Datalogiuddannelse: Hvor er morgendagens softwareingeniører? (dateret 8. januar 2008)
- Hvad er dårlige funktioner i Java?