Wie erkennt die JVM welche class verwendet werden muss?

ArkLut

Aktives Mitglied
Hi,

Ich bin grad vor einem Problem gestanden und hab mir dadurch folgende Frage gestellt.
Ich habe in Package A in JAR 1 folgende Class:
Code:
package org.example.PackageA
import org.example.PackageB.ClassP

public class ClassG {
   int id;
   String name;
   public ClassG() { }
   void doSomething() {
       ClassP cPe = new ClassP()
       int a = cPe.doSomethingSpecial(id, name);   
   }
}

Und dazu habe ich in Jar 2 folgende Class.
Code:
package org.example.PackageB

public class ClassP {

   public ClassP() { }

   public int doSomethingSpecial(int b, String P) {
		return doThis(b, P);   
   }
   
   public int doThis(int b, String P) {
		return b + P.lenght();   
   } 
   
   public int doThat(int b, String P) {
		return b + P.lenght();   
   } 
   
   public int domDiDo(int b, String P) {
		return 1337;   
   } 
}

Das ganze ist kein problem beide Jars am ClassPath und werden geladen.
Wenn class ClassG also die method doSomething() aufruft wird die class ClassP und aus dieser doSomethingSpecial() aufgerufen wird.


Was aber wenn ich die alte Jar 2 durch eines mit folgender ClassP ersetze
Code:
package org.example.PackageB  

public class ClassP {

   public ClassP() { }

   public int doSomethingSpecial(int b, String P) {
		return 3 + 1 + doThat(3,P);   
   }
   
   private void doNothing(int b, String P) {
   } 
   
   private int doThat(int b, String P) {
		return b + P.lenght();   
   }

   public int doNew(int b, int P) {
		return 3 + 1 + doThat(3,P);   
   }   
}

Würde es da zu problemen kommen?
Eigentlich sollte das klappen, da ich ja nur die unveränderte methode aufrufe und die JVM daher keinen grund sieht das abzu lehen.

Dennoch frage ich mich ob die JVM nicht irgend welche sicherheits vorkehrungen hat um so etwas zu verhindern.


PS: Ja ich weis, das man in solchen fällen eigentlich gegen Interfaces Programmiert, und das war auch mein eingangs erwähntes Problem.
 
Was meinst du genau? Für die JVM sind das doch einfach zwei (völlig) unterschiedliche Programme. Es weiß ja nicht, dass in einer vorherigen Ausführung des Java-Prozesses irgendwann einmal die Jar-Datei eine andere war. Bzw. merkt sie sich ja nicht, dass eine Jar-Datei mit demselben Dateisystempfad im Classpath jetzt eine Klasse mit demselben vollqualifizierten Namen aber unterschiedlichem Inhalt enthält.
Um auf deine Frage zurückzukommen, ob das Austauschen denn in irgendeine Weise ein Problem darstellt: Nein. Die JVM linked anhand des vollqualifizierten Klassennamens (also mit Packagename) und der Signatur (+ Rückgabetyp) der aufgerufenen Methode. Du kannst ziemlich viel austauschen, ohne von Java-Sourcedateien neu kompilieren zu müssen. Siehe: https://docs.oracle.com/javase/specs/jls/se8/html/jls-13.html
 
Prinzipiell ist der Vorgang der Prüfung beim Laden einer Klasse in der JVM Specification festgelegt:

https://docs.oracle.com/javase/specs/jvms/se7/html/index.html

https://en.wikipedia.org/wiki/Java_virtual_machine#Class_loader

Ich lese gerade, dass bei der Verifikation nur die Constraints für Class Files allgemein geprüft werden.

Also ist wahrscheinlich eher der Abschnitt Resolution wichtig.

Ich habe diesen jetzt nicht im Detail gelesen.

Ich weiß, dass manchmal beim Bauen (Compilieren) was schief geht und dann gibt es Fehler zur Laufzeit.

Wenn die Namen, Return Typen und Paramter Typen passen, sollte es keine Probleme geben.

Irgendwelche Prüfsummen oder andere Prüfmechanismen gibt es in der JVM nicht.

Sicherer wäre aber, Du kompilierst alle Quelldateien noch mal und ersetzt diese vollständig im Class-/Modul-Pfad für deinen Programmstart.
 
Denke. eh was ich mir gedacht und erwarted habe ...
war mir aber in dem Moment zu unsicher ob ich irgend etwas übersehe und bei mir nur zufällig klappt ..
Passt eigentlich - ist ja auch das selbe Prinzip bei den Interfaces.

Ja und zum nochmal kompilieren bräuchte man den aufrufenden code 😀
 

Zurück
Oben