2011-07-04 10 views
6

Poniżej znajduje się wyciąg z MSDN:Czy CLR/JVM przechowuje pojedynczą pulę intern dla wszystkich działających aplikacji .net/java?

plików wykonywalnych języka wspólnego konserwuje przechowywanie ciąg utrzymując stolik, nazywa stażysta basen, który zawiera jednego odniesienia do każdego unikalnego dosłownym ciąg deklarowanej lub utworzonego programowo w twoim programie. W związku z tym wystąpienie literalnego ciągu o określonej wartości tylko istnieje w systemie.

Na przykład, jeśli przydzielić tego samego dosłownego ciąg kilku zmiennych, runtime pobiera taką samą odniesienie do dosłownego łańcucha z stażysta basenie i przypisuje go do każdej zmiennej .

Metoda Intern wykorzystuje pulę intern do wyszukiwania ciągu równego wartości wartości str. Jeśli taki ciąg istnieje, zwracane jest jego odniesienie w puli internującej: . Jeśli ciąg znaków nie istnieje , odniesienie do str jest dodawane do puli intern, to zwracane jest odwołanie . .... Jeśli próbujesz uzyskać zmniejszyć całkowitą ilość pamięci, którą przydziela twoja aplikacja , pamiętaj o , że interakcja z ciągiem ma dwa niepożądane efekty uboczne: . Po pierwsze, pamięć przydzielona do internowanych obiektów String prawdopodobnie nie zostanie zwolniona , dopóki nie zakończy się wspólne środowisko wykonawcze języka (CLR).

Czy to oznacza, że ​​CLR utrzymuje jedną pulę intern dla wszystkich działających aplikacji .net? Przykład: jeśli program A tworzy literał łańcuchowy "Test" i jeśli inny program próbuje utworzyć inny ciąg literowy "Test", ta sama kopia jest używana? To samo pytanie dotyczy również JVM.

Odpowiedz

2

CLR przechowuje pulę internentów na instancję. Jeśli czytasz dalej w dół MSDN link:

jeśli starają się zmniejszyć całkowitą ilość pamięci przydziela aplikacyjne, należy pamiętać, że interning ciąg ma dwa niepożądane skutki uboczne. Po pierwsze pamięć przydzielona do internowanych obiektów String najprawdopodobniej nie zostanie zwolniona, dopóki nie zakończy się wspólne środowisko uruchomieniowe języka (CLR).

Dla języka Java jest to również za JVM zacząć.

Jednak według this article:

Mit ten idzie w kierunku przeciwnym do mitu 2. Niektórzy ludzie uwierzyć, że zinternalizowane ciągi pozostanie w pamięci, dopóki JVM kończy. To mogło być prawdą dawno temu, ale dziś zinternalizowane łańcuchy są gromadzone w śmieciach, jeśli nie ma już dla nich odniesienia. Zobacz poniżej nieznacznie zmodyfikowaną wersję powyższego programu. Usuwa od czasu do czasu odwołania do zinternalizowanych łańcuchów.Jeśli wykonasz program z jconsole, zobaczysz, że użycie przestrzeni PermGen idzie w górę iw dół, ponieważ Garbage Collector odzyskuje pamięć używaną przez niewymienione wewnętrzne łańcuchy.

Co oznacza, że ​​w internowanych łańcuchach Java rzeczywiście można uzyskać GCed.

+1

Czy masz link? –

1

Nie, ponieważ nie może.
Każda aplikacja działa we własnym wirtualnym obszarze pamięci. Nie można udostępniać danych między dwoma obszarami pamięci.
Należy wziąć pod uwagę sekwencje ładowania/rozładowywania. Byłoby to bardzo skomplikowane i nigdy nie można było usunąć ciągu znaków.
pamiętać także tę część swojej Cytat:

każdy wyjątkowy ciągiem znaków uznane lub utworzone programowo w programie.


OK, tylko czytanie trochę dalej na tej stronie MSDN:

odniesienie CLR do internowanych obiektu String może utrzymywać się po aplikacji lub nawet twoja domena aplikacji , kończy się.

+0

Holterman - linia z MSDN - Najpierw pamięć przydzielona na internowane obiekty String najprawdopodobniej nie zostanie zwolniona, dopóki nie zakończy się wspólne środowisko uruchomieniowe języka (CLR). Wygląda na to, że jest to CLR –

+0

@PK: Czytałem to jako "instancję CLR dla tego programu". –

0

Jeśli chodzi o Javę, tak. Literały łańcuchów są przechowywane w puli na JVM. Fragment z JavaDoc z String#intern(): All literal strings and string-valued constant expressions are interned. String literals are defined in §3.10.5 of the Java Language Specification

+0

są internowani dla jednej aplikacji lub dla całej JVM? –

+0

O ile mi wiadomo, jest jedna pula na JVM. Jednak w normalnym przypadku prawdopodobnie masz jedną maszynę JVM na aplikację - zależy to jednak od definicji aplikacji. W środowisku serwera serwer aplikacji działałby w jednej maszynie JVM i mógł obsługiwać wiele (pod) aplikacji. – Thomas

+0

Sądzę, że pytanie dotyczyło maszyny JVM, która uruchamiała wiele aplikacji przy użyciu oddzielnego programu ładującego klasy dla każdego z nich (na przykład kontenera serwletów), niezależnie od tego, czy jest możliwe, że istnieje wiele pul pośrednich. Byłoby to równoznaczne z pytaniem, czy możemy załadować wiele razy java.lang.String z różnymi programami ładującymi klasy. –

0

Jak rozumiem dla CLR, jest to jeden na środowisko wykonawcze, a nie na AppDomain. Od Jeffrey Richter „CLR za pośrednictwem C#”

Zauważ, że garbage collector nie może uwolnić sznurki że wewnętrzna tabela odnosi się do mieszania, ponieważ tabela hash posiada odniesienie do tych obiektów String. Obiekty ciągów, do których odwołuje się wewnętrzna tablica asocjacyjna, nie mogą zostać zwolnione, dopóki AppDomain nie zostanie rozładowana lub proces nie zostanie zakończony.

Sugeruje to, że tabela jest oddzielona od AppDomain.

JVM nie ma tej koncepcji, więc nie ma dwuznaczności. Możesz mieć różne klasy ładujące, ale trudno sobie wyobrazić, że masz inne ładowanie klasy dla String.

Powiązane problemy