MokaByte Numero 13 - Novembre 1997
Foto
 
Java di Microsoft
 
di
Giovanni
Puliti
Analisi della  piattaforma Java rilasciata da Microsoft alla scoperta di cosa c'è di vero nelle accuse che  Sun sta lanciando contro la casa di Redmond

 


 



E’ la  notizia del momento: la battaglia giudiziaria fra Microsoft e Sun sta infiammando le aule dei tribunali americani e riempiendo le mailing list su Java e non solo. Alla base di tutto ciò vi sarebbe secondo Sun la violazione  da parte di Microsoft degli accordi sulla licenza per lo sviluppo di tecnologia Java non conforme allo standard ufficiale. Vediamo cosa c’è  di  vero in tutto ciò, e quanto invece sia semplicemente frutto di concorrenza politica


 

Introduzione
Nel numero scorso di MB abbiamo annunciato della nascita della battaglia legale che è nata fra Sun e Microsoft, e che sembra monopolizzare l’attenzione di tutti gli addetti del settore. Per coloro che avessero perso le prime battute della storia, facciamo un breve sunto dell’accaduto.
Dopo che Microsoft ha rilasciato le ultime versioni del suo software per Java(Virtual Machine, librerie contenute nell’SDK e tool di sviluppo), Sun ha scoperto che in realtà tali prodotti non rispecchiano completamente lo standard 100%Pure Java. Questo fatto è secondo la casa madre un gravissima inadempienza agli accordi presi, dato che l’obiettivo principale di Java è quello di avere un unico standard per permettere il famoso Write Once Run Evrywhere.
In base ai test e dall’analisi delle librerie effettuati da Sun,  Microsoft avrebbe violato gli accordi commerciali e le specifiche tecniche in due modi:  da un lato introducendo classi aggiuntive non presenti nei package Java core, e dall’altro modificando leggermente quelle presenti.
Queste due operazioni compromettono pesantemente la portabilità di una applicazione Java, dato che nel primo caso, facendo riferimento alle classi estranee, essa non potrà essere eseguita su una VM non Microsoft, mentre al contrario, nel secondo caso, una applicazione 100%Pure Java non potrà girare su una macchina MS (anche se alla luce dell’analisi delle modifiche effettuate, questa seconda possibilità sembra essere meno probabile).
In aggiunta, oltre alle differenze dovute alle modifiche effettuate, Microsoft ha affermato che non intende supportare ne  adesso ne intende farlo in futuro, la tecnologia RMI ed il supporto per il CORBA.
A tal proposito, non è il fatto che attualmente tali tecnologie non siano supportate, a stupire, nemmeno Netscape è in grado di offrire la totale copertura del JDK 1.1,  ma piuttosto che tale mancanza non  sia dovuta a carenze di sviluppo, ma sia voluta, e che non vi verrà posto rimedio né ora né in futuro.
Alla luce di tutto ciò vediamo di far luce su quello che effettivamente è una reale mancanza da parte di MS, e su cosa invece sia semplicemente frutto di guerra commerciale.

Analisi delle differenze
Sulla base del confronto delle classi contenute nell’ultima versione dell’SDK, la 2.0 (per capirsi quella su cui si basa l’Internet Explorer 4.0), si può certamente affermare che in effetti Microsoft ha rilasciato una versione non esattamente conforme a quella ufficiale di Sun. Il problema principale è che è necessario stabilire quanto sia grande la differenza, e soprattutto, se tali discrepanze siano tali da compromettere la tanto leggendaria portabilità di Java.  Secondo il comunicato ufficiale del portavoce di Sun, l’operato del concorrente è sicuramente grave, dato che sono state modificate profondamente le classi appartenenti ai package fondamentali del core-Java; in aggiunta, Sun ha rincarato la dose dicendo che  tale iniziativa è ancora più grave in quanto non completamente documentata, ma smascherabile solo dopo  accurate analisi delle varie librerie con appositi tool decompilatori (il javap del JDK o il ClassView di MS).
Come prima cosa ci chiediamo quali possano essere state le modifiche eseguite e quale peso possano avere prese singolarmente.  Ovviamente la cosa più immediata che si può immaginare comprometta lo standard sia la modifica della firma dei metodi o del tipo di alcune variabili di base, come la modifica del nome di alcune classi. Un tale tipo di operazione però è molto forte, quindi  facilmente smascherabile,  e non necessaria per introdurre un po’ di incompatibilità, ed è per questo che è stata eseguita con moderazione,  modificando alcune interfacce.
Al contrario è molto meno intrusivo, ma altrettanto efficace, introdurre del materiale aggiuntivo non compatibile con lo standard 100% Pure Java, in modo da vincolare le applicazioni che ne fanno uso alla sola piattaforma Java di Microsoft.
Questo tipo di alterazione è stata quella maggiormente  operata da Microsoft:  in particolare  sono state aggiunte nuove classi, nuovi metodi e nuove variabili, più tutto il package ms.com, che offre la strada più breve per rendere un programma Java non portabile.
Un ultimo tipo di operazione eseguita è stata quella di eliminare certi metodi rinominandoli con una firma completamente diversa.
Si potrebbe infine effettuare una comparazione delle differenze comportamentali fra il software di Sun e quello di MS, ma questa non è una valutazione comprovante delle effettive differenze fra le due piattaforme.
Sulla base delle prove effettuare si può affermare che la maggior parte dei problemi è stata riscontrata nei package java.lang(nuovi metodi, nuove variabili), java.io(metodi eliminati), java.awt(nuove classi), java.util(nuovi metodi, nuove variabili) e java.security(interfacce modificate), praticamente tutti i più importanti:
 

Classi, metodi e variabili aggiunte
La prima modifica rappresenta le classi introdotte nei package di sistema, quelli che formano il core Java API: un package di sistema è qualcosa che inizia per Java.* nella sua denominazione completa.
Nell’insieme delle classi aggiuntive, 16 appartengono alla AWT (il set dei componenti grafici):
 

Le nuove classi di Microsoft  per i componenti AWT peers
WButtonPeer WCheckboxMenuItemPeer WCheckboxPeer WChoicePeer
WLabelPeer WListPeer WMenuBarPeer WMenuItemPeer
WMenuPeer WPopupMenuPeer WScrollbarPeer WScrollPanePeer
WTextAreaPeer WTextComponentPeer WTextFieldPeer WUIPeer
Tabella 1

 

Ad eccezione dell’ultima, tutte le classi sono componenti peer (un peer component è un oggetto grafico il cui aspetto e comportamento è fortemente dipendente dalla piattaforma del sistema operativo sottostante). Normalmente tali classi dovrebbero trovarsi in pacchetti diversi, come ad esempio sun.awt.windows o sun.awt.motif, in modo da evitarne l’uso se non strettamente necessario.
Per quanto riguarda i metodi, si deve dire che il metodo più frequentemente aggiunto è il getBaseName(): fortunatamente  è anch’esso privato relativamente al package, per cui non si dovrebbero incontrare grossi problemi.
Altri cambiamenti come ad esempio la trasformazione del classloader  LoadClassinternal() in metodo privato piuttosto che in package private, sono dovute a differenze di implementazione interne, e non dovrebbero comportare  effetti sullo sviluppatore.
Non si intende con questo minimizzare il problema, ma fintanto che lo sviluppatore non debba andare ad interagire con queste classi in profondità nella VM, non  dovrebbero insorgere problemi di incompatibilità.
A tal proposito si ricordi che, in base alle regole del 100%PJ (VEDI MB XXX), tali operazioni sono da evitare nella maniera più assoluta, se si vuole mantenere il proprio software portabile secondo la filosofia Java.
I veri problemi sorgono con i metodi pubblici introdotti da MS:
 

Metodi pubblici aggiunti nelle libreirie fondamentali 
Class New Method(s)
java.awt.EventQueue _postEvent (AWTEvent)
java.awt.Font getNativeData()
java.awt.image.ColorModel finalize() [was protected]
java.awt.image.DirectColorModel getToolkitData()
java.awt.image.IndexColorModel getOpaque() 
getToolkitData()
java.awt.SystemColor getWin32Index()
java.lang.Class getInterface(String) 
getMethods(int[]) 
getMethodFromSignature(String,String) 
getDeclaredMethodFromSignature(String,String)
java.lang.Runtime getNativeServices()
java.lang.SecurityManager checkFileDialog() 
checkMultimedia() 
checkRegistry(int,String) 
checkSystemStreams(int)
java.lang.VerifyError getAuditDetails() 
getAuditIdentifier() 
getClassName() 
getMethodName() 
getPC() 
getViolationCode() 
getViolationDescription()
java.lang.reflect.Method getDescriptor() 
getParameterCount()
java.util.Locale Locale(String, String, String, int, int) 
getCodePage() 
getDefaultLocaleList() 
getLCID() [was private] 
getLocaleFromLCID(int)
java.util.ResourceBundle getMenu (String) 
getMenuBar(String)
Tabella 2

Si devono evitare tutti i metodi della tabella precedente se non si vuole che le proprie applicazioni siano eseguibili solo su piattaforma MS.
Inoltre sono disponibili tre nuove variabili e una serie di Locale per l’internazionalizzazione.
 

Variabili aggiunte nelle Java API
Class New Variable
java.awt.Font pData
java.awt.SystemColor appWorkspace
java.lang.reflect.Member PUBLIC_DECLARED
java.util.Locale
AFRIKAANS 
ALBANIAN 
AUSTRALIA 
BASQUE 
BELGIAN 
BELGIAN_FRENCH 
BRAZILIAN 
BULGARIAN 
BYELORUS 
CATALAN 
CROATIAN 
CZECH 
DANISH 
DUTCH 
ESTONIAN 
FINNISH 
GERMAN_AUSTRIAN 
GERMAN_SWISS 
GREEK 
HEBREW
HUNGARIAN 
ICELANDIC 
INDONESIAN 
IRELAND 
JAPANESE_VERTICAL
KOREAN_VERTICAL 
LATVIAN 
LITHUANIAN 
MEXICAN 
NEWZEALAND 
NORWEGIAN 
NORWEGIAN_NYNORSK 
POLISH 
PORTUGESE 
ROMANIAN 
RUSSIAN 
SERBIAN 
SIMPLIFIED_CHINESE_VERTICAL 
SINGAPORE 
SLOVAKIAN 
SLOVENIAN 
SOUTH_AFRICA 
SPANISH 
SPANISH_MODERN 
SWEDISH 
SWISS 
THAI 
TRADITIONAL_CHINESE_VERTICAL 
TURKISH 
UKRANIAN 
 
Tabella 3

PUBLIC_DECLARED è una nuova variabile di Member, così come appWorkSpace lo è per SystemColor, mentre pdata da privata diviene pubblica. Si evitino assolutamente.
Un commento particolare deve essere fatto in merito all’introduzione dei nuovi valori per Locale: tale operazione  sembra il frutto della mania di grandezza di  Microsoft, che la porta di tanto in tanto senza volerlo (complici i bug) a definire nuovi standard nazionali, continentali, mondiali, intergalattici (si ricordi l’errato cambiamento nell’ora solare dell’anno scorso di Win 95). In questo caso sembra infatti che gli adepti della casa, al contrario dei  colleghi della setta del Dio Sole (Sun) siano capaci di comprendere nuovi linguaggi,  e per questo sentono il bisogno di estendere tali capacità a tutta la comunità mondiale. Anche se l’intenzione è senza dubbio onorevole, questa iniziativa può portare a problemi senza che ce ne sia effettivamente il bisogno. In ogni caso per evitare di incappare in tali trappole,  è sufficiente  che definiate le vostre istanze di Locale con i dovuti parametri  standard, invece di fare affidamento a quelle ufficiali MS che in alcuni casi non sono disponibili.
Veniamo infine alle interfacce: tale elemento può essere considerata come uno  schema (incompleto) dal quale  una classe deve partire e dalla quale evolversi successivamente. Ebbene per quanto riguarda gli schemi (interfacce) legati alla sicurezza  sono state modificate alcuni dettagli, che sebbene siano piccoli, sono sufficienti per impedire ad applicazioni che fanno riferimento ai vecchi modelli di funzionare. Infatti, dato che tali modifiche consistono nell’aggiunta di metodi, e  dato che, il processo di derivazione da una interfaccia prevede la riscrittura di tutti  i metodi,  l’introduzione di elementi nuovi, rende di fatto errata la derivazione di quelle classi che fanno riferimento alla vecchia versione delle interfacce, quella senza intrusi. In tabella 4 sono riportati I corpi del reato:
 

Metodi aggiuntivi nelle interfacce sulla sicurezza
Interface New Methods
java.security.interfaces.DSAPrivateKey getAlgorithm() 
getEncoded() 
getFormat() 
getParams()
java.security.interfaces.DSAPublicKey getAlgorithm() 
getEncoded() 
getFormat() 
getParams()
Tabella 4

 

Il package com.ms
Questo pacchetto rappresenta un set di classi rilasciate da Microsoft per l’utilizzazione  in ambiente Java, e che sono ovviamente inaccessibili da altre Virtual Machine (come ad esempio quella di Netscape Comunicator): l’utilizzazione di una qualsiasi di queste classi equivale ad intraprendere la via più breve per uscire fuori dallo standard Java  e della portabilità.
Un esempio tipico di come si possa cadere facilmente in tali situazioni è dato dall’utilizzazione di Fontmetrics dalla classe Toolkit (per mezzo del metodo getFontMetrics()): infatti mentre la firma è la stessa (public FontMetrics getFontMetrics()) quello che si riceve indietro è una istanza di com.ms.awt.FontMetricsX. Se considerate tale oggetto come FontMetricsX, allora  l’applicazione non sarà eseguibile fuori da una VM Microsoft.  Se invece si utilizza un FontMetrics si mantiene la portabilità.
Un eccezione a questo inconveniente è rappresentata dalle  Application Foundation Classes (AFC) contenute nel  package ms.com.ui, che essendo scritte in java possono essere utilizzate senza problemi.

Cosa manca nell’SDK
Fra tutte le classi ed i package in analisi, sembra in definitiva che manchi un solo metodo:  si tratta del toString() della classe ByteArrayOutputStream, ed anche se si tratta di un solo metodo, il tipo e la frequenza del suo utilizzo fa dubitare della casualità della scelta.

Stessa famiglia, ma comportamento diverso
Oltre alle differenze  nel codice fra le due versioni del JavaSoftware, vediamo quali sono  le differenze comportamentali dei due mondi: a tal proposito si tenga presente che in generale, versioni differenti di software, anche se compatibili dal punto di vista teorico, portano sempre a delle differenze, proprio a causa delle differenze implementative; per questo motivo forse questo tipo di confronto, fra tutti quelli possibili, è quello meno giustificato.
In aggiunta a tale considerazione, si tenga presente che MS offre il suo Java versione 1.1, mentre Sun è arrivata alla versione 1.1.4. le sotto versioni 1.1.xx sono in realtà dei bug fix, per cui potrebbe sorgere il dubbio che la versione di MS sia arretrata e per questo meno solida. Questo dubbio per quanto plausibile non trova completa giustificazione, dato che le due case non sono allineate temporalmente per il rilascio delle VM, e quindi non è detto che la versione della casa di Redmond sia necessariamente più scadente (si potrebbe calcolare che la MS VM 1.1 sia equivalente ad una di Sun targata 1.1.2).
Forse verrebe da obiettare che essendo Sun la casa che ha inventato Java, e che è quella che attualmente che sta investendo maggiori risorse,  si dovrebbe adottare come standard universalmente riconosciuto quello introdotto da Sun, ma ovviamente in questo caso si introducono esigenze legali e politiche.
Tralasciando questi particolari  tecnici e di marketing, differenze di comportamento sussistono, ed in genere portano la VM di Ms ad essere meno rigorosa. Ad esempio si è potuto osservare che utilizzando  la classe java.util.BorderLayout, ed immettendo  un oggetto in  un panel senza il quadrant-name, con il JDK o JRE l’oggetto finisce per disporsi automaticamente al centro dello schermo, mentre se invece lo si aggiunge con un nome illegale di quadrante come ad esempio “TOP “ , viene generata una eccezione del tipo IllegalArgumentException.
Nel caso in cui si utilizzi invece la VM di Microsoft in entrambi i casi l’oggetto non viene visualizzato ma non vengono generate  eccezioni.
Altra differenza è che la classe Dialog accetta sotto Microsoft parent=null, mentre in tal caso il JDK genera una eccezione.

Conclusioni
Senza dubbio possiamo dire che Microsoft ha volontariamente effettuato delle modifiche alle classi base di JDK, e anche se le modifiche in certi casi sono minime, o trasparenti si trattano pur sempre di modifiche.
Se  tali variazioni siano legali o meno, e se la causa ingiunta da Sun sia giustificata, solo le aule dei tribunali ed il tempo potranno darci risposta. Per il momento possiamo dire che se non si effettuano attenti controlli sul tipo di operazioni effettuate, si rischia di cadere in situazioni pericolose fortemente legate alla piattaforma MS e quindi in totale contrapposizione con la filosofia principale di Java.
Vediamo di fare una sintesi di quello che è emerso alla fine dell’analisi fatta:

Mancanza del supporto per RMI e JNI: nel caso in cui tali strumenti diventino necessari si dovrà ricorrere a soluzioni alternative (non MS come JRE o direttamente il JDK) o ricorrere a soluzioni antecedenti  (come ad esempio all’utilizzazione di protocolli proprietari per invocare servizi di un server remoto al posto di RMI).   Anche se una applet  offre  innegabili  vantaggi rispetto all’applicazione, in certi casi questa seconda opzione diviene l’unica possibile se si è scelto di utilizzare MS.

Aggiunta di classi, metodi e variabili: se si desidera sviluppare applicazioni 100% PJ si dovrà assolutamente evitare tali elementi. Anche se il compito di evitare tali ostacoli non è difficile, non è presente nessun meccanismo del tipo @deprecated come con i metodi obsoleti.

Aggiunta di  metodi ad interfacce: questo punto è uno dei più insidiosi di tutta l’operato di MS: infatti se una vecchia  applicazione (o una costruita secondo 1000%PJ) viene fatta eseguire sulla nuova VM  non funzionerà correttamente o affatto fino a che tutti i metodi delle interfacce saranno aggiunti (ovviamente vuoti dato che non erano previsti).  Questa rimessa a modello dovrebbe creare applicazioni nuovamente 100% PJ.

Mancanza  del  metodo ByteArrayOutputStream: anche se si tratta di un solo metodo è forse una delle mancanze più gravi, ed anche se può essere aggirata facilmente  obbliga a modifiche  e  ricompilazioni e  sarebbero potute essere facilmente evitate.

Il package  com.ms: differentemente da quanto avviene per le altre modifiche in questo caso, che uno dei più radicali contro la portabilità, non è altrettanto rischiosa dato che il pacchetto non è pubblicamente accessibile dall’esterno.

Differenze comportamentali: anche se le varie modifiche sono state fatte cercando poi di mantenere lo stesso tipo di comportamento delle classi, questo a volte non avviene. Come detto precedentemente, dato l’alto numero di variabili in gioco, tali divergenze sono comprensibili indipendentemente dal fatto che MS abbia seguito una strada sua.
 

A prescindere dalle effettive incompatibilità tecniche,  sembra che nuovamente stia nascendo un antagonismo a due fra giganti dell’informatica, come già in passato è avvenuto per la guerra IBM e Apple: anche se in genere le agitazioni portano dopo un primo periodo di scompiglio, a nuovi scenari, in genere più interessanti, per il momento siamo in piena randomizzazione,  e non penso che si possa adesso fruire positivamente della cosa.
Anche se da un certo punto di vista adesso le cose sono più chiare (si sono finalmente gettate le maschere, e si sono mostrate le vere intenzioni), credo che tale situazione non si esaurisca brevemente, ed anzi porti ad un periodo pericolosamente lungo di stagnazione.
 
  

 

MokaByte rivista web su Java

MokaByte ricerca nuovi collaboratori
Chi volesse mettersi in contatto con noi può farlo scrivendo a mokainfo@mokabyte.it