# hashCode() == Speicheradresse? => warum nur int?



## gerry (3. Apr 2009)

Hallo

Der hashCode eines objekts gibt ja die Speicheradresse des objekts zurück - als int. Nun ist bei uns die Frage aufgetaucht, was passiert, wenn man unter einem 64 Bit Betriebssystem über 4gb ram drinnen hat - was macht java da, wenn es den eindeutigen hashCode erzeugen muss?

Oder unterstützt die 64 Bit Version von Java nicht mehr als 4gb ram pro Anwendung?

Sorry für die sinnlose Frage, aber wenn Informatiker so reden kommen solche blöden Fragen einfach auf. Und wenn man es mal gehört hat, will man es auch wissen 

Danke schon mal, 
lg Gerald


----------



## tfa (3. Apr 2009)

> Der hashCode eines objekts gibt ja die Speicheradresse des objekts zurück


Niemand behauptet, dass das so sein muss:



			
				Java Doc hat gesagt.:
			
		

> (This is _typically_ implemented by converting the internal address of the object into an integer, but this implementation technique _is not required_ by the JavaTM programming language.)


----------



## Ebenius (3. Apr 2009)

Die API-Doc sagt: 





> As much as is reasonably practical, the hashCode method defined by class Object does return distinct integers for distinct objects. (This is typically implemented by converting the internal address of the object into an integer, but this implementation technique is not required by the Java™ programming language.)


Ein ganz einfacher Überlauf wäre also eine Lösung. Das größere Problem bekommt man mit System.identityHashCode(). Die API-Doc sagt, dass diese Methode den gleichen HashCode zurück liefert wie die hashCode-Implementierung der Object-Klasse. Die API-Doc von _identityHashCode()_ verspricht zwar nicht, dass der zurückgelieferte Wert eindeutig ist, der Name suggeriert dies aber. 

Ebenius


----------



## Spacerat (3. Apr 2009)

Ich weiss zwar nicht genau wie "Object.hashCode()" implementiert ist (kann ja sein das die Speicheradresse dort zur Berechnung herangezogen wird), aber der Hashcode selber ist sonst alles andere als blos oder überhaupt noch eine Speicheradresse.


----------



## tfa (3. Apr 2009)

Das Problem mit den Speicheradressen ist ja auch, dass die sich innerhalb der Lebenszeit eines Objekts ändern können. Wenn das Auswirkungen auf den Hashcode hätte, wäre das ziemlich schrecklich. Ich glaube, dieser Hinweis in der API-Docu ist ziemlich veraltet.


----------



## Stefan S. (3. Apr 2009)

tfa hat gesagt.:


> Das Problem mit den Speicheradressen ist ja auch, dass die sich innerhalb der Lebenszeit eines Objekts ändern können. Wenn das Auswirkungen auf den Hashcode hätte, wäre das ziemlich schrecklich. Ich glaube, dieser Hinweis in der API-Docu ist ziemlich veraltet.



Nein, die API ist nicht veraltet. Der Hashcode ändert sich deshalb nicht, weil es sich um Speicheradressen handelt, die von der JVM verwaltet werden. Der Hashcode wird beibehalten, auch wenn der GC das Objekt verschiebt. 

Man sollte sich nicht auf die Methode hashCode für Object verlassen. Wird die JVM bewegt, ändert sich der Hash.


----------



## gerry (3. Apr 2009)

Stefan S. hat gesagt.:


> Man sollte sich nicht auf die Methode hashCode für Object verlassen. Wird die JVM bewegt, ändert sich der Hash.



Das ist aber eigentlich schlecht - Einige Datenstrukturen nutzen diesen Mechanismus ja zur eindeutigen Identifizierung von Objekten, oder?


----------



## Marco13 (3. Apr 2009)

Ich hab' mich auch gefragt, was zum Hen.. mit einem "Bewegen der JVM" gemeint sein könnte... aber habe die Gesamtaussage dann wohlwollendn dahingehend interpretiert, dass man sich, wenn man ein Programm zweimal hintereinander startet, NICHT darauf verlassen kann, dass in beiden Durchläufen für die gleichen Objekte auch die gleichen hashCodes entstehen. 

Aber man KANN sich darauf verlassen, dass der HashCode eines Objektes während EINES Programmdurchlaufes sich nicht "einfach so" ändert (außer ggf. wenn das Objekt geändert wird und so...)


----------



## Spacerat (3. Apr 2009)

Also: Soweit ich das verstanden habe, bekommt "hashCode()" erst in Verbindung mit "equals()" eine ernstzunehmende Bedeutung. Ansonsten sollte "hashCode()" für jede Instanz möglichst verschiedene Werte zurückgeben, die sich dann zur Laufzeit nicht mehr andern sollten. Dafür die Speicheradresse zu verwenden drängt sich ja beinahe auf. Ich wollte deswegen auch schon mal "equals()" ohne bzw. "equals()" über "hashCode()" implementieren... war ziemlich blamabel... für mich 
http://www.java-forum.org/java-basics-anfaenger-themen/81069-equals-hashcode-contract.html


----------



## Stefan S. (3. Apr 2009)

gerry hat gesagt.:


> Das ist aber eigentlich schlecht - Einige Datenstrukturen nutzen diesen Mechanismus ja zur eindeutigen Identifizierung von Objekten, oder?



Innerhalb der Plattform bleib der Hash auch dank der JVM gleich. Nur darauf kann man sich verlassen. Sun hat dafür ein ausgeklügeltes Konzept entwickelt. Das Ganze ist ohnehin völlig nebensächlich, weil die virtuelle Maschine die Speicherverwaltung des Betriebssystems ohnehin noch weiter abstrahiert. Realle Speicheradressen bekommst weder du, noch die JVM jemals zu Gesicht. 



Marco13 hat gesagt.:


> Ich hab' mich auch gefragt, was zum Hen.. mit einem "Bewegen der JVM" gemeint sein könnte... aber habe die Gesamtaussage dann wohlwollendn dahingehend interpretiert, dass man sich, wenn man ein Programm zweimal hintereinander startet, NICHT darauf verlassen kann, dass in beiden Durchläufen für die gleichen Objekte auch die gleichen hashCodes entstehen.
> 
> Aber man KANN sich darauf verlassen, dass der HashCode eines Objektes während EINES Programmdurchlaufes sich nicht "einfach so" ändert (außer ggf. wenn das Objekt geändert wird und so...)



Der Hash bleibt auf dem System gleich. Auch wenn du das Programm neu ausführst oder den Computer neu startest. Sobald du die JVM aber bewegst, d.h. auf einem anderen Computer ausführst, erhälst du auch einen anderen Hash.


----------



## SlaterB (3. Apr 2009)

> Auch wenn du das Programm neu ausführst oder den Computer neu startest.

nach welchen Regeln das denn?
ist irgendwo festgelegt, dass ein String "xyz" die Adresse a hat und wenn ich eine ArrayList exakt 255 ms nach Programmstart erzeugt, dass die dann Adresse b hat?
was passiert wenn ich Millionen von Objekten nach Zufallsprinzip erzeuge wie quasi in jedem höheren Programm?
um welche Objekte/ Adressen gehts überhaupt?


----------



## Spacerat (3. Apr 2009)

SlaterB hat gesagt.:


> um welche Objekte/ Adressen gehts überhaupt?


Offenbar geht es darum, das die native Methode "Object.hashCode()" die Speicheradresse des jeweiligen Objektes zu dessen Berechnung heranzieht.


----------



## Stefan S. (3. Apr 2009)

SlaterB hat gesagt.:


> um welche Objekte/ Adressen gehts überhaupt?



Wenn wir von Hashcodes reden, dann ist überhaupt nichts sicher, solange die Daten bzw. Objekte nicht kanonisch vorliegen. Um welche Objekte es ging? Es ging um die Frage ob der Hashcode von Object während der Programmausführung gleich bleibt und warum das der Fall ist, wenn die Speicheradresse des Objektes dafür herangezogen wird, während die GC die Objekte verschiebt.


----------



## Ebenius (3. Apr 2009)

Stefan S. hat gesagt.:


> Es ging um die Frage...


Nö.  Es ging eigentlich darum, dass der Themeneröffner mit (anderen) Informatikern zusammen beim Bier gesessen hat und die Überlegung aufkam: Wenn der IdentityHashCode aus der Speicher-Adresse ermittelt wird und nur vom Typ _int_ ist, kann man dann darauf schließen, dass Java-VMs API-halber keine Prozesse mit mehr als 4GB Speicher verwalten können dürfen?

Und die Antwort war: Nein. 

Ebenius


----------



## gerry (3. Apr 2009)

Jetzt habe ich mich etwas gespielt, weil ich das ganze mal praktisch ausprobieren wollte. 

Mein Plan war: Mal etliche kleine Objekte (z.b. booleans) anlegen und innerhalb einer Schleife zu einer Liste hinzufügen. 
Damit die Liste selber beim Index nicht übergeht, übergebe ich der Liste gleich boolean- Arrays mit so ca. 10 Mio booleans. 

Doch da das Problem: Bei knapp 70 Millionen booleans (also beim 7ten Durchlauf) kommt ein 
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
        at test.Main.main(Main.java:21)
Java Result: 1

Laut TaskManager sind das knappe 70 MB Arbeitsspeicher (an dem dürfte es eigentlich nicht fehlen - sind ja 8 gig drinnen). 

Habs dann mal probiert mit auslesen von einem 1 MB File und dieses "aufzuheben" --> selbes Ergebnis - Das Java- Prog stürzt bei knapp 70 MB RAM- Verbrauch ab. 

Kann mir das jemand erklären? Unterstützt Java nicht mehr als 70 MB Ram?

Source: 
[highlight=Java]package test;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Random;

public class Main {

    public static void main(String[] args) throws IOException {
        while (true) {
            Random rand = new Random();
            boolean[] arr = new boolean[10000000];
            //mit irgendwas sinnlosem befüllen...
            for (int l = 0; l < 10000000; l++) {
                arr[l] = rand.nextInt(1) == 1;
            }
            list.add(arr);

            System.out.println((++count) + " * 10 Mio boolean");
            System.in.read();
        }
    }

    static int count = 0;
    static ArrayList<boolean[]> list = new ArrayList<boolean[]>();
}[/highlight]


----------



## gerry (3. Apr 2009)

Ebenius hat gesagt.:


> Und die Antwort war: Nein. Ebenius



Wie es ausschaut sind nicht 4 gb die Grenze, sondern 70 MB 

lg Gerald


----------



## Ebenius (3. Apr 2009)

Das ist einstellbar. Tipp mal auf der Konsole: 
	
	
	
	





```
java -X
```
... und dann lies Dir -Xmx, -Xms, ... durch.

Ebenius


----------



## Stefan S. (4. Apr 2009)

Ebenius hat gesagt.:


> Nö.  Es ging eigentlich darum, dass der Themeneröffner mit (anderen) Informatikern zusammen beim Bier gesessen hat und die Überlegung aufkam: Wenn der IdentityHashCode aus der Speicher-Adresse ermittelt wird und nur vom Typ _int_ ist, kann man dann darauf schließen, dass Java-VMs API-halber keine Prozesse mit mehr als 4GB Speicher verwalten können dürfen?
> 
> Und die Antwort war: Nein.



Java verwaltet sowieso keine Prozesse, das macht das Betriebssystem. 

Man kann sich ja mal anschauen was Java eigentlich macht.


```
// hashCode() generation :
//
// Possibilities:
// * MD5Digest of {obj,stwRandom}
// * CRC32 of {obj,stwRandom} or any linear-feedback shift register function.
// * A DES- or AES-style SBox[] mechanism
// * One of the Phi-based schemes, such as:
//   2654435761 = 2^32 * Phi (golden ratio)
//   HashCodeValue = ((uintptr_t(obj) >> 3) * 2654435761) ^ GVars.stwRandom ;
// * A variation of Marsaglia's shift-xor RNG scheme.
// * (obj ^ stwRandom) is appealing, but can result
//   in undesirable regularity in the hashCode values of adjacent objects
//   (objects allocated back-to-back, in particular).  This could potentially
//   result in hashtable collisions and reduced hashtable efficiency.
//   There are simple ways to "diffuse" the middle address bits over the
//   generated hashCode values:
//

static inline intptr_t get_next_hash(Thread * Self, oop obj) {
  intptr_t value = 0 ;
  if (hashCode == 0) {
     // This form uses an unguarded global Park-Miller RNG,
     // so it's possible for two threads to race and generate the same RNG.
     // On MP system we'll have lots of RW access to a global, so the
     // mechanism induces lots of coherency traffic.
     value = os::random() ;
  } else
  if (hashCode == 1) {
     // This variation has the property of being stable (idempotent)
     // between STW operations.  This can be useful in some of the 1-0
     // synchronization schemes.
     intptr_t addrBits = intptr_t(obj) >> 3 ;
     value = addrBits ^ (addrBits >> 5) ^ GVars.stwRandom ;
  } else
  if (hashCode == 2) {
     value = 1 ;            // for sensitivity testing
  } else
  if (hashCode == 3) {
     value = ++GVars.hcSequence ;
  } else
  if (hashCode == 4) {
     value = intptr_t(obj) ;
  } else {
     // Marsaglia's xor-shift scheme with thread-specific state
     // This is probably the best overall implementation -- we'll
     // likely make this the default in future releases.
     unsigned t = Self->_hashStateX ;
     t ^= (t << 11) ;
     Self->_hashStateX = Self->_hashStateY ;
     Self->_hashStateY = Self->_hashStateZ ;
     Self->_hashStateZ = Self->_hashStateW ;
     unsigned v = Self->_hashStateW ;
     v = (v ^ (v >> 19)) ^ (t ^ (t >> 8)) ;
     Self->_hashStateW = v ;
     value = v ;
  }

  value &= markOopDesc::hash_mask;
  if (value == 0) value = 0xBAD ;
  assert (value != markOopDesc::no_hash, "invariant") ;
  TEVENT (hashCode: GENERATE) ;
  return value;
}
```

Man sieht, der hashCode() wird nur auf Basis der Speicheradresse berechnet. Eine Garantie auf eindeutigen Hashcode gibt es nicht.


----------



## Ebenius (4. Apr 2009)

Stefan S. hat gesagt.:


> Man sieht, der hashCode() wird nur auf Basis der Speicheradresse berechnet. Eine Garantie auf eindeutigen Hashcode gibt es nicht.


Und genau hier ist dann die Methode _System.identityHashCode(...)_ äußerst ungünstig benannt. Der Rest war klar. 

Ebenius


----------



## gerry (4. Apr 2009)

Ok, Danke mal an alle. 

@Stefan S.: Cool, wo hast du den c- Source her? Den besten Beweis bringt man immer noch mit dem Source - da kann man fast nicht mehr wiedersprechen - gefällt mir 


@Ebenius: Super tipp, leider schaff ich es nicht über 2gig
Ergebnis: 
Could not reserve enough space for object heap
Could not create the Java virtual machine.
Java Result: 1


@alle: Nachdem ich es anscheinend in Java nicht schaffe, mehr als 2 Gigabyte für eine Anwendung zu verwenden, wird das mit der maximalen Anzahl an Objekten > 4 Milliarden nichts werden. 
Weil - das hab ich ja ganz verdrängt - Java ja sogar für einen boolean 1 ganzes Byte reserviert (so ne Verschwendung). 
Jetzt weiß ich wenigstens, dass ich mich trotzdem nie 100% auf den hashCode verlassen kann...


PS: übrigens - hab es in .net, C# auch probiert - da braucht ja ein bool wirklich nur 1 Bit - hier ist es möglich, boolsche Werte einzulagern bis der Speicher platzt 7 gig waren kein Problem...hier gibt es dasselbe Problem mit dem hashCode, wobei ich aber noch schauen muss, wie die das machen - aber wahrscheinlich ähnlich. 

hmm, ich hoffe der Text "C#" steht in einem Java Forum nicht auf der schwarzen Liste - in den Forumregeln hätt ich zumindest nichts entdeckt


----------



## Marco13 (4. Apr 2009)

:noe:

Also... "identityHashCode" heißt ja nicht "uniqueHashCode" oder "hashCodeThatUniqelyDefinesTheObjectOnEveryComputerThatWillEverExist"... es holt nur den "echten" HashCode, egal, wie irgendein besoffener Benutzer die hashCode-Methode überschrieben hat.

Und @gerry: _Jetzt weiß ich wenigstens, dass ich mich trotzdem nie 100% auf den hashCode verlassen kann..._

Was genau meinst du mit "verlassen"?


----------



## Ebenius (4. Apr 2009)

gerry hat gesagt.:


> da kann man fast nicht mehr wi*e*dersprechen


Nicht mal, wenn man ein 'e' weg lässt. 



Marco13 hat gesagt.:


> :noe:
> 
> Also... "identityHashCode" heißt ja nicht "uniqueHashCode" oder "hashCodeThatUniqelyDefinesTheObjectOnEveryComputerThatWillEverExist"... es holt nur den "echten" HashCode, egal, wie irgendein besoffener Benutzer die hashCode-Methode überschrieben hat.


In dem Kontext ist aber eine IdentityHashMap dann schlecht benannt, oder?  Hast aber schon recht. Ich meinte doch oben nur: Der Name suggeriert eben was anderes. Heißt ja nicht, dass er gleich falsch ist.

Ebenius


----------



## Stefan S. (4. Apr 2009)

gerry hat gesagt.:


> @Stefan S.: Cool, wo hast du den c- Source her? Den besten Beweis bringt man immer noch mit dem Source - da kann man fast nicht mehr wiedersprechen - gefällt mir



OO machts maöglich. 




gerry hat gesagt.:


> Weil - das hab ich ja ganz verdrängt - Java ja sogar für einen boolean 1 ganzes Byte reserviert (so ne Verschwendung).
> Jetzt weiß ich wenigstens, dass ich mich trotzdem nie 100% auf den hashCode verlassen kann...
> 
> 
> PS: übrigens - hab es in .net, C# auch probiert - da braucht ja ein bool wirklich nur 1 Bit - hier ist es möglich, boolsche Werte einzulagern bis der Speicher platzt 7 gig waren kein Problem...



Aber garantiert nicht. Moderne Computer sind byte-adressiert, weniger als ein Byte kann man also gar nicht adressieren. In C# ist ein System.Boolean implementierungsabhängig, die Implementierungen schwanken zwischen 1 Byte bis zu 4 Byte. 

Das .NET Framework stellt eine System.Collections.BitArray Klasse zur Verfügung. Das hat aber seinen Preis. Da moderne Systeme keine Adressierung von einem Byte gestatten, müssen Shifts auf Bitebene durchgeführt werden. Bei entsprechender Anzahl von Daten und komplexen Operation geht die Performance flöten.


----------



## gerry (4. Apr 2009)

Stefan S. hat gesagt.:


> Aber garantiert nicht. Moderne Computer sind byte-adressiert, weniger als ein Byte kann man also gar nicht adressieren. In C# ist ein System.Boolean implementierungsabhängig, die Implementierungen schwanken zwischen 1 Byte bis zu 4 Byte.
> 
> Das .NET Framework stellt eine System.Collections.BitArray Klasse zur Verfügung. Das hat aber seinen Preis. Da moderne Systeme keine Adressierung von einem Byte gestatten, müssen Shifts auf Bitebene durchgeführt werden. Bei entsprechender Anzahl von Daten und komplexen Operation geht die Performance flöten.



Mein lieber Stefan, da muss ich dir leider widersprechen (@Ebenius: jetzt ohne e  ) - .Net reserviert wirklich nur 1 Bit (also 1/8 Byte), wenn man beispielsweise Arrays anlegt - da braucht es nicht mal ein BitArray. 

Probier es einfach mal aus 

Gerald


----------



## Stefan S. (4. Apr 2009)

gerry hat gesagt.:


> Mein lieber Stefan, da muss ich dir leider widersprechen (@Ebenius: jetzt ohne e  ) - .Net reserviert wirklich nur 1 Bit (also 1/8 Byte), wenn man beispielsweise Arrays anlegt - da braucht es nicht mal ein BitArray.



Du kannst mir noch zehnmal erzählen das sich die Sonne um die Erde dreht, Fakt ist das es *falsch* ist. Ich habe dir erklärt dass das speichertechnisch auf modernen Rechnern unmöglich ist. Ein Bit ist nicht adressierbar. 

Auszug aus der CLI:



> "*1.1.2 Boolean data type*
> 
> A CLI Boolean type occupies 1 byte in memory. A bit pattern of all zeroes denotes a value of false. A bit pattern with any one or more bits set (analogous to a non-zero integer) denotes a value of true."


Alle .NET Typen werden über das Betriebssystem auf reale Systemtypen gemappt. Demzufolge zeigt mir das Programm bei der folgenden Zeile auch 1 Byte an.


```
Console.WriteLine(sizeof(System.Boolean).ToString());
```

Was glaubst du warum Microsoft eine Klasse namens BitArray zur Verfügung stellt? Zum Spaß? ;(


----------



## Ebenius (4. Apr 2009)

Wieso denn "Boolean". Hab zwar schon Jahre nichts mehr mit C# gemacht, aber soweit ich weiß gibt es auch dort einen primitiven "bool"-Typ. Außerdem spricht gerry von bool-Arrays, was nochmal anders gehandhabt werden kann. Ich weiß nicht, wie der Compiler damit umgeht, und vielleicht hast Du (Stefan S.) Recht, aber die Argumentation hilft überhaupt nicht, dies zu belegen.

BitArrays (man ist das lange her) können bestimmt OR, XOR, AND, was auch eine Existenzberechtigung wäre, wenn bool-Arrays ein Bit pro bool benötigten.

Ebenius


----------



## Stefan S. (4. Apr 2009)

Ebenius hat gesagt.:


> Wieso denn "Boolean". Hab zwar schon Jahre nichts mehr mit C# gemacht, aber soweit ich weiß gibt es auch dort einen primitiven "bool"-Typ.



System.Boolean ist nichts anderes als bool. Primitive Datentypen werden in .NET direkt auf Typen in der FCL abgebildet.



Ebenius hat gesagt.:


> Außerdem spricht gerry von bool-Arrays, was nochmal anders gehandhabt werden kann.



Es wird überhaupt nichts anders gehandhabt, weil der Speicher nicht bitweise adressiert werden kann. Das ist eine Hardwarekonstante!



Ebenius hat gesagt.:


> Ich weiß nicht, wie der Compiler damit umgeht, und vielleicht hast Du (Stefan S.) Recht, aber die Argumentation hilft überhaupt nicht, dies zu belegen.



Selbstverständlich belegt das mein Beitrag. Oder ist die offene ECMA Spezifikation neuerdings falsch?

EDIT: Achja, hier ein Statement von einem bekannten C# *MVP*.



			
				Mattias Sjögren hat gesagt.:
			
		

> It doesn't, it takes one byte (the smallest size you can address). You
> can check that yourself with sizeof(bool). Any MSND topics that says
> otherwise are wrong. If you want to store a lot of boolean values with
> just a single bit each, use a BitArray.
> ...



Das ist exakt dasselbe, was ich bereits sagte. Ein Byte ist der größte addressierbare Speicherbereich in der Maschine. Sehr exotische Embedded Systeme einmal ausgenommen.

Die CPU stellt für dafür Single Instructions zur Verfügung, die hochperformant arbeiten. Wird auf Bitebene gearbeitet muss geshifted werden, was erheblich auf die Performance geht. Ein boolean Array hat deshalb in Java und auch in .NET mindestens die Größe von 1 Byte, sofern keine Abstraktionsklassen eingesetzt werden, die auf Shifts mit all den daraus entstehenden Konsequenzen zurückgreifen.

Und damit ihr Freunde mich hier nicht vollkommen für blöd verkauft, habe ich hier ein extra einmal ein dissasemliertes Listing gemacht.


```
.class private auto ansi beforefieldinit SizeOf.Program
       extends [mscorlib]System.Object
{
  .method private hidebysig static void  Main(string[] args) cil managed
  {
    .entrypoint
    // Code size       84 (0x54)
    .maxstack  4
    .locals init ([0] bool[] b)
    IL_0000:  ldc.i4.s   10
    IL_0002:  newarr     [mscorlib]System.Boolean
    IL_0007:  stloc.0
    IL_0008:  ldloc.0
    IL_0009:  ldc.i4.0
    IL_000a:  ldc.i4.0
    IL_000b:  stelem.i1
    IL_000c:  ldloc.0
    IL_000d:  ldc.i4.1
    IL_000e:  ldc.i4.0
    IL_000f:  stelem.i1
    IL_0010:  ldloc.0
    IL_0011:  ldc.i4.2
    IL_0012:  ldc.i4.1
    IL_0013:  stelem.i1
    IL_0014:  ldloc.0
    IL_0015:  ldc.i4.3
    IL_0016:  ldc.i4.1
    IL_0017:  stelem.i1
    IL_0018:  ldloc.0
    IL_0019:  ldc.i4.4
    IL_001a:  ldc.i4.1
    IL_001b:  stelem.i1
    IL_001c:  ldloc.0
    IL_001d:  ldc.i4.5
    IL_001e:  ldc.i4.0
    IL_001f:  stelem.i1
    IL_0020:  ldloc.0
    IL_0021:  ldc.i4.6
    IL_0022:  ldc.i4.1
    IL_0023:  stelem.i1
    IL_0024:  ldloc.0
    IL_0025:  ldc.i4.7
    IL_0026:  ldc.i4.1
    IL_0027:  stelem.i1
    IL_0028:  ldloc.0
    IL_0029:  ldc.i4.8
    IL_002a:  ldc.i4.0
    IL_002b:  stelem.i1
    IL_002c:  ldloc.0
    IL_002d:  ldc.i4.s   9
    IL_002f:  ldc.i4.1
    IL_0030:  stelem.i1
    IL_0031:  ldloc.0
    IL_0032:  ldc.i4.0
    IL_0033:  ldelem.i1
    IL_0034:  box        [mscorlib]System.Boolean
    IL_0039:  ldloc.0
    IL_003a:  ldc.i4.1
    IL_003b:  ldelem.i1
    IL_003c:  box        [mscorlib]System.Boolean
    IL_0041:  ldloc.0
    IL_0042:  ldc.i4.2
    IL_0043:  ldelem.i1
    IL_0044:  box        [mscorlib]System.Boolean
    IL_0049:  call       string [mscorlib]System.String::Concat(object,
                                                                object,
                                                                object)
    IL_004e:  call       void [mscorlib]System.Console::WriteLine(string)
    IL_0053:  ret
  } // end of method Program::Main

  .method public hidebysig specialname rtspecialname 
          instance void  .ctor() cil managed
  {
    // Code size       7 (0x7)
    .maxstack  8
    IL_0000:  ldarg.0
    IL_0001:  call       instance void [mscorlib]System.Object::.ctor()
    IL_0006:  ret
  } // end of method Program::.ctor

} // end of class SizeOf.Program
```
Wie man sieht allokiert die CLR auch bei einem bool Array ganz normal den Datentyp System.Boolean aus der mscorlib. Es wird nix geshifted und nix gexort.

Wollt ihr mir nun weiterhin Märchen erzählen? ;(


----------



## gerry (4. Apr 2009)

hmm, ok, klingt eigentlich doch plausibel. 

Bin übrigens draufgekommen, warum bei mir um einiges weniger an Speicher verbraucht wurde 

Folgendes ist passiert: Ich habe eine "0" vergessen bei der for- Schleife, die das Feld initialisiert hat - dadurch wurde um eine zehner- Potenz weniger Elemente mit einem Wert versehen - die CLR hat anscheinend den Rest wegoptimiert....peinlicher Fehler 

Also Stefan, ich glaube dir jetzt :toll:


----------



## Ebenius (4. Apr 2009)

Und ich hab die Wahreit von Stefans Kernaussage gar nicht in Frage gestellt. Trotzdem: Etwas unentspannt, der Zeitgenosse.

Ebenius


----------

