La ligne de fond est, oui, c'est faisable. On peut changer le nom d'une classe interne, donc il est plus court que le nom original attribué par javac
.
je cherchais à travers The Java Language Specification et The Java Virtual Machine Specification pour trouver où il parle de l'utilisation du caractère $
pour désigner une classe interne, et n'a pas été en mesure de trouver une référence. La raison en est que cela n'a pas vraiment d'importance.
Case et le point:
class A {
class B {
class C {}
}
A() {
new B().new C();
}
public static void main(String[] s){
new A();
}
}
Ici, nous avons des classes internes imbriquées. Lors de la compilation, nous obtenons les fichiers suivants:
A.class
A$B.class
A$B$C.class
Voici une expérience rapide:
- Ouvrez le fichier
A.class
, et changer la référence à A$B$C
et le changement à ABCDE
.Renommez le A$B$C.class
en ABCDE.class
. Ouvrez le ABCDE.class
et remplacez la référence par ABCDE
.
- Exécutez
java A
, vérifiez s'il s'exécute.
Note: La raison pour laquelle la A$B$C
a été changé à ABCDE
est parce que le changement de la longueur de l'identifiant semble mutiler le format de fichier class
et provoquera une erreur. L'explication technique sera à la fin de ce post.
Résultat? Ça marche. La raison est dans le fichier class
. Voici un démontage du A.class
, et seules les parties pertinentes d'origine:
Compiled from "A.java"
class A extends java.lang.Object
SourceFile: "A.java"
InnerClass:
#10= #3 of #7; //B=class A$B of class A
#22= #2 of #3; //C=class A$B$C of class A$B
// ... snip ... //
const #2 = class #21; // A$B$C
// ... snip ... //
const #21 = Asciz A$B$C;
// ... snip ...//
fin de compte, le nom des classes internes ne sont que des noms dans la piscine constante.
Si le nom de la classe A$B$C
dans la piscine constante de A.class
est changé en ABCDE
, et si le nom du fichier de classe A$B$C
et nom dans le fichier class
est modifié, la machine virtuelle Java heureux exécuter avec le nouveau classe interne nommée.
Qu'est-ce que cela signifie?
Il n'est pas nécessaire d'utiliser le MyClass$1$1$1 ... $1
pour le nom de la classe, mais tout ce qui est nécessaire à la suite, il serait donc possible d'avoir plus de combinaisons dans un nom de fichier plus court.
Comment quelqu'un pourrait-il aller et faire cela? Que je vais laisser comme un exercice au lecteur.
Note sur l'utilisation de ABCDE
comme le nouveau nom de la classe
Dans ce post, le nom de la classe imbriquée interne, A$B$C
a été changé pour ABCDE
de garder la longueur du nom de la classe même, dans afin d'empêcher un ClassFormatError
d'être lancé. La raison en est que le CONSTANT_Utf8_info
structure du pool constant a une propriété length
qui indique la longueur de la chaîne. Je n'étais pas en mesure de modifier la longueur pendant que je modifiais le fichier class
dans un éditeur de texte.
Afin de raccourcir la chaîne dans le pool constant, je suppose que l'on devrait modifier la valeur du champ length
pour refléter la longueur de la chaîne elle-même.
Mise à jour
Oui, il est possible de modifier constant_pool du fichier class
pour raccourcir le nom de la classe interne. J'ai pu changer la classe ABCDE
en classe Z
.
est ici une partie du démontage du A.class
:
Compiled from "A.java"
class A extends java.lang.Object
SourceFile: "A.java"
InnerClass:
#10= #3 of #7; //B=class A$B of class A
#22= #2 of #3; //C=class Z of class A$B
// ... snip ...//
const #2 = class #21; // Z
// ... snip ...//
const #21 = Asciz Z;
// ... snip ...//
Comme on le voit, la classe interne est maintenant désignée par Z
, plutôt que A$B$C
.
Le changement a été effectué par la recherche de la chaîne A$B$C
dans les A.class
et A$B$C.class
fichiers, et le remplacer par Z
et changer le caractère avant la chaîne de la valeur 0x05
-0x01
, indiquant que la longueur de la chaîne est maintenant 1
plutôt que 5
.
Avec ces changements, avec renommer le fichier à Z.class
, le programme a couru comme si rien ne s'est jamais produit. Donc, oui, c'est possible de raccourcir le nom de la classe interne aussi.
Vous avez des classes imbriquées sur 100 niveaux de profondeur ?! Merde sainte. :) – Bombe