Java >> Java tutorial >  >> Tag >> java.lang

Hvordan er det muligt, at java.lang.Object er implementeret i Java?

Du kan ændre java.lang.Object (f.eks. ved at tilføje public static void main() metode), men for at blive indlæst og brugt af JVM, skal den modificerede klasse tilføjes til bootstrap-klassestien.

På JDK 8 kan dette gøres med

java -Xbootclasspath/p:<path>

På JDK 9+ kræver dette patching java.base modul:

java --patch-module java.base=<path>

Når JVM starter, indlæser den java.lang.Object af bootstrap-klasseindlæseren ligesom enhver anden klasse, så java.lang.Object med den tilføjede main metode kan faktisk udføres:

$ java -Xbootclasspath/p:. java.lang.Object
Hello world from custom java.lang.Object!

Men hvis du prøver at fjerne eksisterende java.lang.Object metoder, tilføje nye virtuelle metoder, tilføje felter eller på anden måde ændre det eksisterende layout - dette vil ikke virke. Mest sandsynligt vil JVM'en bare gå ned med den fatale fejl.

Dette skyldes, at JVM forventer java.lang.Object at have det kendte layout. Der er hårdkodede forskydninger i JVM-kildekoden, referencer til de afsluttende metoder osv. Det samme gælder for andre iboende klasser som java.lang.String , java.lang.Class , java.lang.ref.Reference og lignende.

Hvad angår Objects superklasse, er der en undtagelse, der udtrykkeligt er beskrevet i JVM Specification:

Hvis værdien af ​​super_class elementet er nul, så skal denne klassefil repræsentere klassen Object, den eneste klasse eller grænseflade uden en direkte superklasse.

Både Java-kompileren og JVM kender til denne undtagelse og håndhæver denne regel ved kompilering af Object.java og ved indlæsning af Object.class .


Du kan implementere java.lang.Object i Java, og den faktiske klasse, du bruger, er faktisk blevet oprettet fra Object.java fil, der leveres med JDK.

Java®-sprogspecifikationen siger i kapitel 8. Klasser:

Hver klasse undtagen Object er en udvidelse af (det vil sige en underklasse af) en enkelt eksisterende klasse (§8.1.4) og kan implementere grænseflader (§8.1.5).

Altså fraværet af supertyper for Object er fastsat i sproget.

Du kan bruge kildekoden til dit eksperiment og prøve at tilføje en extends eller implements klausul og se, at compileren vil afvise det.

Når du kompilerer klassen java.lang.Object , vil den resulterende klassefil være den eneste, der ikke har nogen supertype. Se Java® Virtual Machine Specification, §4.1., ClassFile Structure:

superklasse

For en klasse, værdien af ​​super_class elementet skal enten være nul eller skal være et gyldigt indeks i constant_pool bord. Hvis værdien af ​​super_class elementet er ikke-nul, constant_pool indgang i det indeks skal være en CONSTANT_Class_info struktur, der repræsenterer den direkte superklasse af klassen defineret af denne class fil. Hverken den direkte superklasse eller nogen af ​​dens superklasser må have ACC_FINAL flag sat i access_flags element i dens ClassFile struktur.

Hvis værdien af ​​super_class elementet er nul, så denne class fil skal repræsentere klassen Object , den eneste klasse eller grænseflade uden en direkte superklasse.

For en grænseflade, værdien af ​​super_class element skal altid være et gyldigt indeks i constant_pool bord. constant_pool indgang i det indeks skal være en CONSTANT_Class_info struktur, der repræsenterer klassen Object .

Så selv grænseflader har en indgang for superklassen i klassefilen (der peger på Object ) og klassefilen for java.lang.Object er den eneste med nul tilmelding til superklassen.

Når du prøver at indlæse din version af Object klasse under runtime, falder du over det faktum, at du ikke kan indlæse klasser af java.lang pakke (eller enhver klasse, hvis kvalificerede navn starter med java. ) gennem klassestien generelt.

Før Java 9 skulle du konfigurere bootstrap-klassenstien for at inkludere din version. Startende med Java 9, klassen java.lang.Object skal tilhøre java.base modul, som indlæses på en implementeringsspecifik måde. Du skal bruge --patch-module mulighed for at injicere din egen version.

Men du skal passe på med, hvad du skriver ind i din egen version. Der er mange forventninger fra andre klasser og miljøet, og hvis de ikke opfyldes, kan det bryde (dårligt).

JLS, §4.3.2. Klasseobjektet viser de forventede metoder og links til andre kapitler, der definerer speciel sprogsemantik for nogle af dem.


Det er et rigtig fedt eksperiment. Men det er sådan, Java fungerer

  1. Da hver klasse i Java skal udvide java.lang.Object , din tilpassede Object klasse udvider også det.
  2. For at indlæse en klasse skal Java indlæse dens overordnede klasser. Så når Java forsøger at køre main() metode i din brugerdefinerede Object klasse, indlæser den den rigtige java.lang.Object klasse.
  3. Så snart ægte java.lang.Object klasse er indlæst, prøver JVM at køre main() metode i den klasse. Da den ikke eksisterer, fejler din applikation med.

Java tag