Gibt es in Java eine sizeof-ähnliche Methode?

78

Gibt es in Java eine integrierte Methode, um die Größe eines Datentyps zu ermitteln? Gibt es eine Möglichkeit, Größe zu finden?

Ankit Sachan
quelle
9
Vielleicht finden Sie javaworld.com/javaworld/javaqa/2003-12/02-qa-1226-sizeof.html eine interessante Lektüre (was übrigens das erste Ergebnis war, das ich beim Googeln nach "sizeof Java" erhielt).
Dominic Rodger

Antworten:

61

Nein. In der Standard-Java SE-Klassenbibliothek gibt es keine solche Methode.

Nach Ansicht der Designer wird es in Java nicht benötigt, da die Sprache die Notwendigkeit beseitigt, dass eine Anwendung 1 weiß, wie viel Speicherplatz für einen primitiven Wert, ein Objekt oder ein Array mit einer bestimmten Anzahl von Elementen reserviert werden muss.

Sie könnten denken, dass ein Operator sizeof für Personen nützlich wäre, die wissen müssen, wie viel Speicherplatz ihre Datenstrukturen beanspruchen. Sie können diese und weitere Informationen jedoch auch einfach und zuverlässig mit einem Java-Speicherprofiler abrufen, sodass keine sizeof-Methode erforderlich ist.


Frühere Kommentatoren machten den Punkt, sizeof(someType)der lesbarer wäre als 4. Wenn Sie dieses Argument der Lesbarkeit akzeptieren, liegt das Mittel in Ihren Händen. Definieren Sie einfach eine Klasse wie diese ...

public class PrimitiveSizes {
    public static int sizeof(byte b) { return 1; } 
    public static int sizeof(short s) { return 2; }
    // etcetera
}

... und statisch importieren ...

import static PrimitiveSizes.*;

Oder definieren Sie einige benannte Konstanten. z.B

public static final int SIZE_OF_INT = 4;

Oder (Java 8 und höher) verwenden Sie die Integer.BYTESKonstante und so weiter.


Warum haben die Java-Designer dies nicht in Standardbibliotheken implementiert? Meine Vermutung ist, dass:

  • sie glauben nicht, dass es notwendig ist,
  • sie glauben nicht, dass es eine ausreichende Nachfrage dafür gibt, und
  • Sie denken nicht, dass es die Mühe wert ist.

Es gibt auch das Problem, dass die nächste Nachfrage nach einer sizeof(Object o)Methode wäre, die mit technischen Schwierigkeiten behaftet ist.

Das Schlüsselwort oben ist "sie"!


1 - Ein Programmierer muss möglicherweise wissen, um platzsparende Datenstrukturen zu entwerfen. Ich kann mir jedoch nicht vorstellen, warum diese Informationen zur Laufzeit über einen Methodenaufruf im Anwendungscode benötigt werden.

Stephen C.
quelle
14

Aus dem Artikel in JavaWorld

Eine oberflächliche Antwort ist, dass Java nichts wie Cs sizeof () liefert. Lassen Sie uns jedoch überlegen, warum ein Java-Programmierer dies gelegentlich möchte.

Der AC-Programmierer verwaltet die meisten Speicherzuordnungen für die Datenstruktur selbst, und sizeof () ist für die Kenntnis der zuzuweisenden Speicherblockgrößen unverzichtbar. Darüber hinaus tun C-Speicherzuordnungen wie malloc () bei der Objektinitialisierung fast nichts: Ein Programmierer muss alle Objektfelder festlegen, die Zeiger auf weitere Objekte sind. Aber wenn alles gesagt und codiert ist, ist die C / C ++ - Speicherzuweisung ziemlich effizient.

Im Vergleich dazu sind Java-Objektzuweisung und -Konstruktion miteinander verbunden (es ist unmöglich, eine zugewiesene, aber nicht initialisierte Objektinstanz zu verwenden). Wenn eine Java-Klasse Felder definiert, die auf weitere Objekte verweisen, werden diese häufig auch zur Erstellungszeit festgelegt. Durch das Zuweisen eines Java-Objekts werden daher häufig zahlreiche miteinander verbundene Objektinstanzen zugewiesen: ein Objektdiagramm. In Verbindung mit der automatischen Speicherbereinigung ist dies allzu praktisch und kann dazu führen, dass Sie sich nie um Details zur Java-Speicherzuweisung kümmern müssen.

Dies funktioniert natürlich nur für einfache Java-Anwendungen. Im Vergleich zu C / C ++ belegen äquivalente Java-Datenstrukturen tendenziell mehr physischen Speicher. In der Entwicklung von Unternehmenssoftware ist die Annäherung an den maximal verfügbaren virtuellen Speicher der heutigen 32-Bit-JVMs eine häufige Einschränkung der Skalierbarkeit. Ein Java-Programmierer könnte daher von sizeof () oder ähnlichem profitieren, um zu beobachten, ob seine Datenstrukturen zu groß werden oder Speicherengpässe enthalten. Glücklicherweise können Sie mit Java Reflection ein solches Tool ganz einfach schreiben.

Bevor ich fortfahre, werde ich auf einige häufige, aber falsche Antworten auf die Frage dieses Artikels verzichten. Irrtum: Sizeof () wird nicht benötigt, da die Größen der Java-Basistypen festgelegt sind

Ja, ein Java-Int ist 32 Bit in allen JVMs und auf allen Plattformen, aber dies ist nur eine Sprachspezifikationsanforderung für die vom Programmierer wahrnehmbare Breite dieses Datentyps. Ein solches int ist im Wesentlichen ein abstrakter Datentyp und kann beispielsweise durch ein physisches 64-Bit-Speicherwort auf einer 64-Bit-Maschine gesichert werden. Gleiches gilt für nicht primitive Typen: Die Java-Sprachspezifikation sagt nichts darüber aus, wie Klassenfelder im physischen Speicher ausgerichtet werden sollen oder dass ein Array von Booleschen Werten nicht als kompakter Bitvektor in der JVM implementiert werden kann. Irrtum: Sie können die Größe eines Objekts messen, indem Sie es in einen Byte-Stream serialisieren und die resultierende Stream-Länge anzeigen

Der Grund, warum dies nicht funktioniert, ist, dass das Serialisierungslayout nur eine Fernreflexion des tatsächlichen In-Memory-Layouts ist. Eine einfache Möglichkeit, dies zu erkennen, besteht darin, zu untersuchen, wie Strings serialisiert werden: Im Speicher beträgt jedes Zeichen mindestens 2 Byte, in serialisierter Form sind Strings jedoch UTF-8-codiert, sodass jeder ASCII-Inhalt halb so viel Speicherplatz beansprucht

Ramesh
quelle
6
"Glücklicherweise können Sie mit Java Reflection ein solches Tool ganz einfach schreiben." Wie?
dfrankow
Ich habe mich immer gefragt, wie groß eine Referenz ist und was darin enthalten ist.
Marichyasana
11

Die Java Native Access- Bibliothek wird normalerweise zum Aufrufen nativer gemeinsam genutzter Bibliotheken aus Java verwendet. Innerhalb dieser Bibliothek gibt es Methoden zum Bestimmen der Größe von Java-Objekten:

Die getNativeSize(Class cls)Methode und ihre Überladungen geben die Größe für die meisten Klassen an.

Wenn Ihre Klassen von der Strukturklasse von JNA erben, ist die calculateSize(boolean force)Methode alternativ verfügbar.

Iain Sproat
quelle
1
Vielen Dank für diese Antwort! Ich habe versucht, JNA zu verwenden, wo ein Argument mit Cs sizeof () abgeleitet wird, und genau das habe ich gebraucht!
Daniel Widdis
@sprocketonline - die Links sind defekt, könnten Sie sie bitte aktualisieren
Naman
10

Sie können Bitmanipulationen wie unten ausführen, um die Größe der Grundelemente zu erhalten:

public int sizeofInt() {
    int i = 1, j = 0;
    while (i != 0) {
        i = (i<<1); j++;
    }
    return j;
}

public int sizeofChar() {
    char i = 1, j = 0;
    while (i != 0) {
        i = (char) (i<<1); j++;
    }
    return j;
}
Murali Mohan
quelle
2
sizeof (in C) gibt die Anzahl der Bytes zurück, während diese Routinen die Anzahl der Bits zurückgeben würden.
LarsH
5
Wenn Sie i<<8stattdessen verwenden, wird die Anzahl der Bytes angegeben.
Richard Sun
Ja, Sie können die Bytes / Bits so berechnen, aber das ist nicht erforderlich. Die Java-Sprachspezifikation garantiert, dass sich die Anzahl der Bytes, die zur Darstellung jedes primitiven Typs benötigt werden, niemals ändern wird.
Stephen C
9

Wie hier erwähnt , gibt es Möglichkeiten, die Größe primitiver Typen durch ihre Wrapper zu ermitteln.

zB für a longkönnte dies Long.SIZE / Byte.SIZEvon Java 1.5 (wie bereits von zeodtr erwähnt ) oder Long.BYTESvon Java 8 sein

Herr Tsjolder
quelle
4

Es gibt einen zeitgemäßen Weg, dies für Primitive zu tun. Verwendung BYTESvon Typen.

System.out.println("byte " + Byte.BYTES);
System.out.println("char " + Character.BYTES);
System.out.println("int " + Integer.BYTES);
System.out.println("long " + Long.BYTES);
System.out.println("short " + Short.BYTES);
System.out.println("double " + Double.BYTES);
System.out.println("float " + Float.BYTES);

Es fuehrt zu,

byte 1
char 2
int 4
long 8
short 2
double 8
float 4
snr
quelle
3

Sie können Integer.SIZE / 8, Double.SIZE / 8 usw. für primitive Typen aus Java 1.5 verwenden.

zeodtr
quelle
1

Die Instrumentation-Klasse verfügt über eine getObjectSize () -Methode. Sie sollten sie jedoch nicht zur Laufzeit verwenden müssen. Der einfachste Weg, die Speichernutzung zu untersuchen, ist die Verwendung eines Profilers, mit dem Sie die Speichernutzung verfolgen können.

Peter Lawrey
quelle
1

Ich habe beschlossen, eine Aufzählung zu erstellen, ohne die Standard-Java-Konventionen zu befolgen. Vielleicht gefällt dir das.

public enum sizeof {
    ;
    public static final int FLOAT = Float.SIZE / 8;
    public static final int INTEGER = Integer.SIZE / 8;
    public static final int DOUBLE = Double.SIZE / 8;
}
Siamaster
quelle
1

Versuchen Sie es mit java.lang.Instrumentation.getObjectSize (Object) . Aber bitte beachten Sie das

Es gibt eine implementierungsspezifische Annäherung an die vom angegebenen Objekt verbrauchte Speichermenge zurück. Das Ergebnis kann einen Teil oder den gesamten Overhead des Objekts enthalten und ist daher für den Vergleich innerhalb einer Implementierung nützlich, jedoch nicht zwischen Implementierungen. Die Schätzung kann sich während eines einzelnen Aufrufs der JVM ändern.

StarPinkER
quelle
0

Auf SourceForge.net ist eine Klasse / JAR verfügbar, die Java-Instrumente verwendet, um die Größe eines Objekts zu berechnen. Hier ist ein Link zur Beschreibung: java.sizeOf

Andy King
quelle
0

Nur ein paar Tests darüber:

public class PrimitiveTypesV2 {

public static void main (String[] args) {
    Class typesList[] = {
            Boolean.class , Byte.class, Character.class, Short.class, Integer.class,
            Long.class, Float.class, Double.class, Boolean.TYPE, Byte.TYPE, Character.TYPE,
            Short.TYPE, Integer.TYPE, Long.TYPE, Float.TYPE, Double.TYPE
        };
    
    try {               
        for ( Class type : typesList ) {
            if (type.isPrimitive()) {
                System.out.println("Primitive type:\t" + type); 
            }
            else {
                boolean hasSize = false;
                java.lang.reflect.Field fields[] = type.getFields();
                for (int count=0; count<fields.length; count++) {
                    if (fields[count].getName().contains("SIZE")) hasSize = true;
                }
                if (hasSize) {
                    System.out.println("Bits size of type " + type + " :\t\t\t" + type.getField("SIZE").getInt(type) );
                    double value = type.getField("MIN_VALUE").getDouble(type);
                    long longVal = Math.round(value);
                    if ( (value - longVal) == 0) {
                        System.out.println("Min value for type " + type + " :\t\t" + longVal );
                        longVal = Math.round(type.getField("MAX_VALUE").getDouble(type));
                        System.out.println("Max value for type " + type + " :\t\t" + longVal );
                    }
                    else {
                        System.out.println("Min value for type " + type + " :\t\t" + value );
                        value = type.getField("MAX_VALUE").getDouble(type);
                        System.out.println("Max value for type " + type + " :\t\t" + value );
                    }
                }
                else {
                    System.out.println(type + "\t\t\t type without SIZE field.");
                }
            } // if not primitive
        } // for typesList
    } catch (Exception e) {e.printStackTrace();}
} // main
} // class PrimitiveTypes
Javier Puche
quelle
-1

Ich glaube nicht, dass es in der Java-API ist. Die meisten Datentypen, die eine Reihe von Elementen enthalten, verfügen jedoch über eine size()Methode. Ich denke, Sie können leicht eine Funktion schreiben, um die Größe selbst zu überprüfen?

Alfred
quelle
-1

ja..in JAVA

System.out.println(Integer.SIZE/8);  //gives you 4.
System.out.println(Integer.SIZE);   //gives you 32.

//Similary for Byte,Long,Double....
Akash -_-
quelle