Kritiek op Java - Criticism of Java

De programmeertaal Java en het Java-softwareplatform zijn bekritiseerd vanwege ontwerpkeuzes, waaronder de implementatie van generieke geneesmiddelen, geforceerde objectgeoriënteerde programmering, de verwerking van niet-ondertekende getallen, de implementatie van drijvende-kommaberekeningen en een geschiedenis van beveiligingsproblemen in de primaire Java. VM-implementatie, HotSpot . Software die in Java is geschreven, met name de vroege versies, is bekritiseerd vanwege de prestaties in vergelijking met software die in andere programmeertalen is geschreven. Ontwikkelaars hebben ook opgemerkt dat er rekening moet worden gehouden met verschillen in verschillende Java-implementaties bij het schrijven van complexe Java-programma's die met alle Java-programma's moeten werken.

Taalsyntaxis en semantiek

Merkloos product

Toen generieke geneesmiddelen aan Java 5.0 werden toegevoegd, was er al een groot raamwerk van klassen (waarvan er vele al waren verouderd ), dus werden generieke geneesmiddelen geïmplementeerd met behulp van typeverwijdering om migratiecompatibiliteit en hergebruik van deze bestaande klassen mogelijk te maken. Dit beperkte de functies die konden worden geboden, in vergelijking met andere talen.

Omdat generieke geneesmiddelen worden geïmplementeerd met behulp van typeverwijdering, is het werkelijke type van een sjabloonparameter E tijdens runtime niet beschikbaar. De volgende bewerkingen zijn dus niet mogelijk in 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
    }
}

Naamwoordgerichtheid

Door het ontwerp moedigt Java programmeurs aan om een ​​oplossing te bedenken in termen van zelfstandige naamwoorden (klassen) die met elkaar interageren, en om werkwoorden (methoden) te zien als bewerkingen die op of door dat zelfstandig naamwoord kunnen worden uitgevoerd. Steve Yegge stelt dat dit een onnodige beperking van taalexpressie veroorzaakt, omdat een klasse meerdere functies kan hebben die erop werken, maar een functie is gebonden aan een klasse en kan nooit op meerdere typen werken.

Veel andere multiparadigmatalen ondersteunen functies als een constructie op het hoogste niveau. In combinatie met andere functies zoals functie-overbelasting (één werkwoord, meerdere zelfstandige naamwoorden) en generieke functies (één werkwoord, een familie van zelfstandige naamwoorden met bepaalde eigenschappen), kan de programmeur beslissen of een specifiek probleem in termen van zelfstandige naamwoorden of werkwoorden moet worden opgelost. Java versie 8 introduceerde enkele functionele programmeerfuncties.

Verborgen relatie tussen code en hardware

In 2008 publiceerde het Center Software Technology Support van het Amerikaanse ministerie van Defensie een artikel in het "Journal of Defense Software Engineering" waarin de ongeschiktheid van Java als de eerste onderwezen taal werd besproken. Nadelen waren dat studenten "geen gevoel hadden voor de relatie tussen het bronprogramma en wat de hardware eigenlijk zou doen" en de onmogelijkheid "om een ​​idee te krijgen van de runtime-kosten van wat er wordt geschreven, omdat het buitengewoon moeilijk is om te weten wat een methode-aanroep zal uiteindelijk worden uitgevoerd". In 2005 bekritiseerde Joel Spolsky Java als een overfocused onderdeel van de leerplannen van universiteiten in zijn essay The Perils of JavaSchools . Anderen, zoals Ned Batchelder, zijn het niet eens met Spolsky voor het bekritiseren van de delen van de taal die hij moeilijk te begrijpen vond, en beweerden dat Spolsky's commentaar meer een 'subjectieve tirade' was.

Niet-ondertekende gehele typen

Java mist native niet-ondertekende integer- typen. Niet-ondertekende gegevens worden vaak gegenereerd uit programma's die zijn geschreven in C , en het ontbreken van deze typen verhindert directe gegevensuitwisseling tussen C en Java. Niet-ondertekende grote getallen worden ook gebruikt in een aantal numerieke verwerkingsvelden, waaronder cryptografie, waardoor Java voor deze taken onhandiger kan worden gebruikt. Hoewel het mogelijk is om dit probleem te omzeilen met behulp van conversiecode en grotere gegevenstypen, wordt het gebruik van Java omslachtig voor het verwerken van niet-ondertekende gegevens. Hoewel een 32-bits geheel getal met teken kan worden gebruikt om een ​​16-bits niet-ondertekende waarde zonder verlies vast te houden, en een 64-bits geheel getal met teken een 32-bits geheel getal zonder teken, is er geen groter type om een ​​64-bits geheel getal zonder teken vast te houden. In alle gevallen kan het verbruikte geheugen verdubbelen, en typisch moet elke logica die vertrouwt op two's complement overflow herschreven worden. Indien geabstraheerd, worden functieaanroepen noodzakelijk voor veel bewerkingen die eigen zijn aan sommige andere talen. Als alternatief is het mogelijk om Java's ondertekende gehele getallen te gebruiken om niet-ondertekende gehele getallen van dezelfde grootte te emuleren , maar dit vereist gedetailleerde kennis van bitsgewijze bewerkingen . In JDK 8 was enige ondersteuning voor niet-ondertekende integer-typen, maar niet voor niet-ondertekende bytes en zonder ondersteuning in de Java-taal.

Overbelasting van de operator

Java is bekritiseerd omdat het geen door de gebruiker gedefinieerde operators ondersteunt. Overbelasting door operators verbetert de leesbaarheid, dus de afwezigheid ervan kan Java-code minder leesbaar maken, vooral voor klassen die wiskundige objecten vertegenwoordigen, zoals complexe getallen en matrices. Java heeft slechts één niet-numeriek gebruik van een operator: +voor het aaneenschakelen van tekenreeksen. Maar dit wordt geïmplementeerd door de compiler, die code genereert om StringBuilder-instanties te maken - het is onmogelijk om door de gebruiker gedefinieerde operatoroverbelastingen te creëren.

Samengestelde waardetypen

Java mist samengestelde waardetypes, zoals structs in C, databundels die direct worden gemanipuleerd in plaats van indirect via referenties. Waardetypen kunnen soms sneller en kleiner zijn dan klassen met verwijzingen. Java's HashMapis bijvoorbeeld geïmplementeerd als een reeks verwijzingen naar HashMap.Entryobjecten, die op hun beurt verwijzingen naar sleutel- en waardeobjecten bevatten. Iets opzoeken vereist inefficiënte dubbele dereferentie. Als Entryhet een waardetype zou zijn, zou de array sleutel-waardeparen direct kunnen opslaan, waardoor de eerste indirectheid wordt geëlimineerd, de referentielocatie wordt vergroot en het geheugengebruik en de heapfragmentatie worden verminderd . Verder, als Java generieke primitieve typen zou ondersteunen, zouden sleutels en waarden direct in de array kunnen worden opgeslagen, waardoor beide niveaus van indirectheid worden verwijderd.

Grote arrays

Java is bekritiseerd omdat het geen arrays van 2 31 (ongeveer 2,1 miljard) of meer elementen ondersteunt. Dit is een beperking van de taal; de Java-taalspecificatie , sectie 10.4, stelt dat:

Arrays moeten worden geïndexeerd door int-waarden... Een poging om toegang te krijgen tot een arraycomponent met een lange indexwaarde resulteert in een compileerfout.

Het ondersteunen van grote arrays vereist ook wijzigingen in de JVM. Deze beperking komt tot uiting in gebieden zoals collecties die beperkt zijn tot 2 miljard elementen en het onvermogen om continue bestandssegmenten groter dan 2 GB in het geheugen toe te wijzen. Java mist ook multidimensionale arrays (aaneengesloten toegewezen enkele geheugenblokken die toegankelijk zijn via een enkele indirectheid), wat de prestaties voor wetenschappelijk en technisch computergebruik beperkt.

Er is geen efficiënte manier om arrays in Java te initialiseren. Bij het declareren van een array compileert de JVM deze naar bytecodes met instructies die de elementen tijdens runtime één voor één instellen. Omdat Java-methoden niet groter kunnen zijn dan 64 KB, zullen arrays van zelfs bescheiden afmetingen met waarden die rechtstreeks in de code worden toegewezen, het bericht "Fout: code te groot" geven bij compilatie.

Integratie van primitieven en arrays

Arrays en primitieven zijn enigszins speciaal en moeten anders worden behandeld dan klassen. Dit is bekritiseerd omdat het veel varianten van functies vereist bij het maken van bibliotheken voor algemeen gebruik.

parallellisme

Per Brinch Hansen betoogde in 1999 dat Java's implementatie van parallellisme in het algemeen, en monitors in het bijzonder, niet de garanties en handhaving biedt die nodig zijn voor veilig en betrouwbaar parallel programmeren. Terwijl een programmeur ontwerp en codering kan vaststellen conventies , kan de compiler geen poging om hen te dwingen, zodat de programmeur ongewild kunnen schrijven onveilig of onbetrouwbaar code te maken.

serialisatie

Java biedt een mechanisme dat objectserialisatie wordt genoemd, waarbij een object kan worden weergegeven als een reeks bytes die zijn gegevensvelden bevat, samen met type-informatie over zichzelf en zijn velden. Nadat een object geserialiseerd is, kan het later worden gedeserialiseerd; dat wil zeggen, de type-informatie en bytes die de gegevens vertegenwoordigen, kunnen worden gebruikt om het object in het geheugen opnieuw te creëren. Dit brengt zeer ernstige theoretische en feitelijke veiligheidsrisico's met zich mee.

Rekenen met drijvende komma

Hoewel Java's drijvende- kommaberekening grotendeels gebaseerd is op IEEE 754 ( Standard for Binary Floating-Point Arithmetic ), worden sommige verplichte standaardfuncties niet ondersteund, zelfs niet bij gebruik van de strictfpmodifier, zoals Exception Flags en Directed Roundings. De uitgebreide precisietypes gedefinieerd door IEEE 754 (en ondersteund door veel processors) worden niet ondersteund door Java.

Uitvoering

Vóór 2000, toen de HotSpot VM in Java 1.3 werd geïmplementeerd, was er veel kritiek op de prestaties. Het is aangetoond dat Java werkt met een snelheid die vergelijkbaar is met geoptimaliseerde native code, en moderne JVM- implementaties worden regelmatig gebenchmarkt als een van de snelste beschikbare taalplatforms - meestal niet meer dan drie keer langzamer dan C en C++.

De prestaties zijn aanzienlijk verbeterd sinds vroege versies. De prestaties van JIT-compilers ten opzichte van native compilers bleken in sommige geoptimaliseerde tests behoorlijk vergelijkbaar te zijn.

Java-bytecode kan tijdens runtime worden geïnterpreteerd door een virtuele machine, of tijdens het laden of uitvoeren worden gecompileerd in native code die rechtstreeks op de hardware van de computer wordt uitgevoerd. Interpretatie is langzamer dan native uitvoering, maar compilatie tijdens laad- of runtime heeft een aanvankelijke prestatiestraf. Moderne JVM-implementaties gebruiken allemaal de compilatiebenadering, dus na de eerste opstarttijd zijn de prestaties vergelijkbaar met native code.

Spelontwerper en programmeur John D. Carmack concludeerde in 2005 over Java op mobiele telefoons : "Het grootste probleem is dat Java erg traag is. Op een puur cpu / geheugen / display / communicatieniveau zouden de meeste moderne mobiele telefoons aanzienlijk beter moeten zijn om te gamen platforms dan een Game Boy Advance. Met Java heb je op de meeste telefoons ongeveer de CPU-kracht van een originele 4,77 MHz (sic) IBM-pc en een slechte controle over alles."

Veiligheid

Het Java-platform biedt een beveiligingsarchitectuur die is ontworpen om de gebruiker in staat te stellen niet- vertrouwde bytecode op een "sandbox"-manier uit te voeren ter bescherming tegen kwaadaardige of slecht geschreven software. Deze "sandboxing"-functie is bedoeld om de gebruiker te beschermen door de toegang te beperken tot platformfuncties en API's die door malware kunnen worden misbruikt , zoals toegang tot het lokale bestandssysteem of netwerk, of het uitvoeren van willekeurige opdrachten.

In 2010 was er een aanzienlijke toename van schadelijke software die zich richtte op beveiligingsfouten in de sandbox-mechanismen die worden gebruikt door Java-implementaties, waaronder die van Oracle. Door deze fouten kan niet-vertrouwde code de sandbox-beperkingen omzeilen, waardoor de gebruiker wordt blootgesteld aan aanvallen. Fouten werden verholpen door beveiligingsupdates, maar werden nog steeds uitgebuit op machines zonder de updates.

Critici hebben gesuggereerd dat gebruikers hun Java-installaties niet bijwerken omdat ze niet weten dat ze die hebben, of hoe ze die moeten bijwerken. Veel organisaties beperken de installatie van software door gebruikers, maar implementeren updates traag.

Oracle is bekritiseerd omdat het niet onmiddellijk updates levert voor bekende beveiligingsbugs. Toen Oracle eindelijk een patch uitbracht voor wijdverbreide fouten in Java 7, verwijderde het Java 6 van de machines van gebruikers, ondanks dat het op grote schaal werd gebruikt door bedrijfsapplicaties waarvan Oracle had gezegd dat ze niet werden beïnvloed door de fouten.

In 2007 bracht een onderzoeksteam onder leiding van Marco Pistoia een andere belangrijke tekortkoming van het Java-beveiligingsmodel aan het licht, gebaseerd op stack-inspectie . Wanneer toegang wordt verkregen tot een beveiligingsgevoelige resource, activeert de beveiligingsmanager code die door de call-stack loopt, om te verifiëren dat de codebase van elke methode erop geautoriseerd is om toegang te krijgen tot de resource. Dit wordt gedaan om verwarde plaatsvervangende aanvallen te voorkomen , die plaatsvinden telkens wanneer een legitiem, meer bevoorrecht programma door een ander wordt misleid om zijn autoriteit te misbruiken. Het probleem met verwarde afgevaardigden is een specifiek type escalatie van bevoegdheden . Pistoia merkte op dat wanneer een beveiligingsgevoelige bron wordt benaderd, de code die verantwoordelijk is voor het verkrijgen van de bron mogelijk niet langer op de stapel staat. Een in het verleden uitgevoerde methode kan bijvoorbeeld de waarde van een objectveld hebben gewijzigd dat bepaalt welke bron moet worden gebruikt. Die methodeaanroep staat mogelijk niet meer op de stapel wanneer deze wordt geïnspecteerd.

Sommige machtigingen zijn impliciet gelijk aan die van Java AllPermission. Deze omvatten de toestemming om de huidige beveiligingsmanager te wijzigen (en deze te vervangen door een die mogelijk de stapelinspectie zou kunnen omzeilen), de toestemming om een ​​aangepaste klassenlader te instantiëren en te gebruiken (die ervoor kan kiezen om te associëren AllPermissionmet een kwaadwillende klasse bij het laden ervan), en de toestemming om een ​​aangepaste toestemming te maken (die zichzelf zo krachtig zou kunnen verklaren als AllPermissionvia zijn impliesmethode). Deze problemen zijn gedocumenteerd in de twee boeken van Pistoia over Java Security: Java 2 Network Security (Second Edition) en Enterprise Java Security .

Parallelle installaties

Vóór Java 7 was het normaal dat het installatieprogramma geen oudere Java-installaties detecteerde of verwijderde. Het was heel gewoon op een Windows-computer om meerdere installaties van Java 6 op dezelfde computer te zien, die slechts door een kleine revisie varieerden. Meerdere installaties zijn toegestaan ​​en kunnen worden gebruikt door programma's die afhankelijk zijn van specifieke versies.

Dit heeft tot gevolg dat nieuwe Java-installaties nieuwe taalfuncties en bugfixes kunnen bieden, maar ze corrigeren de beveiligingsproblemen niet, omdat schadelijke programma's de oudere versies kunnen gebruiken.

Java 7 heeft oudere versies van zichzelf bijgewerkt, maar Java 6 of eerder niet.

Automatische updates

Vanaf 2014 zijn veelgebruikte tools van derden (zoals Adobe Flash en Adobe Reader) het onderwerp geweest van onderzoek naar beveiligingsproblemen. Adobe en anderen zijn overgestapt op automatische updates op Windows. Deze vereisen geen actie van de gebruiker en zorgen ervoor dat beveiligingsproblemen snel worden opgelost met minimale inspanning door gebruikers of beheerders.

Vanaf 2015 vereist Java 8 nog steeds dat gebruikers Java zelf updaten. Maar op Windows kunnen alleen degenen met beheerdersrechten software bijwerken. De Windows Java-updater activeert vaak een storende prompt om gebruikersaccountbeheer te verhogen: wat gebruikers ook kiezen, ze krijgen nog steeds hetzelfde bericht "Java moet worden bijgewerkt".

Zie ook

Opmerkingen:

Externe links