DonanımHaber

java etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster
java etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster

Java Collections sınıfı statik metodlarının herbiri için kod örneği





Java Collections sınıfı, bir dizi statik metoda sahiptir ve bu metodlar, çeşitli koleksiyon işlemleri gerçekleştirmek için kullanılır. Her bir metod için basit kod örnekleri aşağıda verilmiştir:


sort(List<T> list): Liste öğelerini doğal sırasına göre sıralar.


java

Copy code

List<Integer> list = Arrays.asList(3, 1, 4, 1, 5, 9);

Collections.sort(list);

System.out.println(list); // [1, 1, 3, 4, 5, 9]


shuffle(List<?> list): Listeyi rastgele sıraya sokar.


java

Copy code

List<Integer> list = Arrays.asList(3, 1, 4, 1, 5, 9);

Collections.shuffle(list);

System.out.println(list); // [9, 1, 5, 3, 1, 4] (örnek çıktı, her seferinde değişebilir)


reverse(List<?> list): Listeyi tersine çevirir.


java

Copy code

List<Integer> list = Arrays.asList(3, 1, 4, 1, 5, 9);

Collections.reverse(list);

System.out.println(list); // [9, 5, 1, 4, 1, 3]


fill(List<? super T> list, T obj): Listeyi belirli bir öğe ile doldurur.


java

Copy code

List<Integer> list = new ArrayList<>(Arrays.asList(3, 1, 4, 1, 5, 9));

Collections.fill(list, 0);

System.out.println(list); // [0, 0, 0, 0, 0, 0]


copy(List<? super T> dest, List<? extends T> src): Bir kaynaktan bir hedefe koleksiyon kopyalar.


java

Copy code

List<Integer> src = Arrays.asList(3, 1, 4, 1, 5, 9);

List<Integer> dest = Arrays.asList(new Integer[src.size()]);

Collections.copy(dest, src);

System.out.println(dest); // [3, 1, 4, 1, 5, 9]


min(Collection<? extends T> coll): Koleksiyondaki en küçük öğeyi döndürür.


java

Copy code

List<Integer> list = Arrays.asList(3, 1, 4, 1, 5, 9);

Integer min = Collections.min(list);

System.out.println(min); // 1


max(Collection<? extends T> coll): Koleksiyondaki en büyük öğeyi döndürür.


java

Copy code

List<Integer> list = Arrays.asList(3, 1, 4, 1, 5, 9);

Integer max = Collections.max(list);

System.out.println(max); // 9


frequency(Collection<?> c, Object o): Belirli bir öğenin koleksiyondaki frekansını döndürür.


java

Copy code

List<Integer> list = Arrays.asList(3, 1, 4, 1, 5, 9);

int freq = Collections.frequency(list, 1);

System.out.println(freq); // 2


binarySearch(List<? extends Comparable<? super T>> list, T key): Listede belirli bir anahtarın ikili aramasını gerçekleştirir.


java

Copy code

List<Integer> list = Arrays.asList(1, 3, 4, 5, 9);

int index = Collections.binarySearch(list, 4);

System.out.println(index); // 2


replaceAll(List<T> list, T oldVal, T newVal): Listedeki tüm eski değerleri yeni değerle değiştirir.


java

Copy code

List<Integer> list = new ArrayList<>(Arrays.asList(3, 1, 4, 1, 5, 9));

Collections.replaceAll(list, 1, 2);

System.out.println(list); // [3, 2, 4, 2, 5, 9]


rotate(List<?> list, int distance): Listeyi belirli bir mesafe kadar döndürür.


java

Copy code

List<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));

Collections.rotate(list, 2);

System.out.println(list); // [4, 5, 1, 2, 3]

swap(List<?> list, int i, int j): Listede iki öğenin yerini değiştirir.


java

Copy code

List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);

Collections.swap(list, 1, 3); // 2. ve 4. öğelerin yerini değiştirir

System.out.println(list); // [1, 4, 3, 2, 5]


indexOfSubList(List<?> source, List<?> target): Kaynak listede hedef listenin ilk oluşumunun başlangıç indeksini döndürür.


java

Copy code

List<Integer> source = Arrays.asList(1, 2, 3, 4, 5, 3, 4);

List<Integer> target = Arrays.asList(3, 4);

int index = Collections.indexOfSubList(source, target);

System.out.println(index); // 2


lastIndexOfSubList(List<?> source, List<?> target): Kaynak listede hedef listenin son oluşumunun başlangıç indeksini döndürür.


java

Copy code

List<Integer> source = Arrays.asList(1, 2, 3, 4, 5, 3, 4);

List<Integer> target = Arrays.asList(3, 4);

int index = Collections.lastIndexOfSubList(source, target);

System.out.println(index); // 5


unmodifiableCollection(Collection<? extends T> c): Değiştirilemeyen bir koleksiyon görünümü döndürür.


java

Copy code

Collection<String> c = Arrays.asList("one", "two", "three");

Collection<String> unmodifiableCollection = Collections.unmodifiableCollection(c);

System.out.println(unmodifiableCollection); // [one, two, three]

// unmodifiableCollection.add("four"); // Bu satır bir UnsupportedOperationException fırlatır


synchronizedCollection(Collection<T> c): Eşzamanlı olarak erişilebilen bir koleksiyon döndürür.


java

Copy code

Collection<String> c = new ArrayList<>();

Collection<String> syncCollection = Collections.synchronizedCollection(c);

syncCollection.add("one");

syncCollection.add("two");

System.out.println(syncCollection); // [one, two]


emptyList(): Boş bir liste döndürür.


java

Copy code

List<Object> emptyList = Collections.emptyList();

System.out.println(emptyList); // []


singletonList(T o): Yalnızca bir öğe içeren bir liste döndürür.


java

Copy code

List<String> singletonList = Collections.singletonList("single");

System.out.println(singletonList); // [single]


emptySet(): Boş bir set döndürür.


java

Copy code

Set<Object> emptySet = Collections.emptySet();

System.out.println(emptySet); // []


singleton(T o): Yalnızca bir öğe içeren bir set döndürür.


java

Copy code

Set<String> singleton = Collections.singleton("single");

System.out.println(singleton); // [single]


emptyMap(): Boş bir map döndürür.


java

Copy code

Map<Object, Object> emptyMap = Collections.emptyMap();

System.out.println(emptyMap); // {}


singletonMap(K key, V value): Tek bir anahtar/değer çifti içeren bir map döndürür.


java

Copy code

Map<String, Integer> singletonMap = Collections.singletonMap("key", 1);

System.out.println(singletonMap); // {key=1}


nCopies(int n, T o): Belirli bir nesnenin n kopyasını içeren bir liste döndürür.


java

Copy code

List<String> nCopies = Collections.nCopies(3, "copy");

System.out.println(nCopies); // [copy, copy, copy]


enumeration(Collection<T> c): Koleksiyondan bir Enumeration döndürür.


java

Copy code

List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);

Enumeration<Integer> enumeration = Collections.enumeration(list);

while (enumeration.hasMoreElements()) {

    System.out.println(enumeration.nextElement());

}

// 1

// 2

// 3

// 4

// 5


list(Enumeration<T> e): Enumeration'dan bir liste döndürür.


java

Copy code

Vector<Integer> vector = new Vector<>(Arrays.asList(1, 2, 3, 4, 5));

Enumeration<Integer> enumeration = vector.elements();

List<Integer> list = Collections.list(enumeration);

System.out.println(list); // [1, 2, 3, 4, 5]


addAll(Collection<? super T> c, T... elements): Belirli öğeleri bir koleksiyona ekler.


java

Copy code

List<Integer> list = new ArrayList<>();

Collections.addAll(list, 1, 2, 3, 4, 5);

System.out.println(list); // [1, 2, 3, 4, 5]


disjoint(Collection<?> c1, Collection<?> c2): İki koleksiyonun ortak öğelerinin olup olmadığını kontrol eder. Eğer hiç ortak öğeleri yoksa true döner.


java

Copy code

List<Integer> list1 = Arrays.asList(1, 2, 3);

List<Integer> list2 = Arrays.asList(4, 5, 6);

boolean isDisjoint = Collections.disjoint(list1, list2);

System.out.println(isDisjoint); // true


checkedCollection(Collection<E> c, Class<E> type): Tip-güvenli bir koleksiyon döndürür.


java

Copy code

List rawList = new ArrayList();

List<String> checkedList = Collections.checkedList(rawList, String.class);

rawList.add("string"); // Doğru kullanım

// rawList.add(1); // Yanlış kullanım, runtime'da ClassCastException fırlatır

System.out.println(checkedList); // [string]


checkedMap(Map<K,V> m, Class<K> keyType, Class<V> valueType): Anahtar ve değer tiplerine göre tip-güvenli bir map döndürür.


java

Copy code

Map rawMap = new HashMap();

Map<String, Integer> checkedMap = Collections.checkedMap(rawMap, String.class, Integer.class);

rawMap.put("key", 1); // Doğru kullanım

// rawMap.put("key", "value"); // Yanlış kullanım, runtime'da ClassCastException fırlatır

System.out.println(checkedMap); // {key=1}


checkedSet(Set<E> s, Class<E> type): Tip-güvenli bir set döndürür.


java

Copy code

Set rawSet = new HashSet();

Set<String> checkedSet = Collections.checkedSet(rawSet, String.class);

rawSet.add("element"); // Doğru kullanım

// rawSet.add(1); // Yanlış kullanım, runtime'da ClassCastException fırlatır

System.out.println(checkedSet); // [element]


checkedList(List<E> list, Class<E> type): Tip-güvenli bir liste döndürür.


java

Copy code

List rawList = new ArrayList();

List<String> checkedList = Collections.checkedList(rawList, String.class);

rawList.add("string"); // Doğru kullanım

// rawList.add(1); // Yanlış kullanım, runtime'da ClassCastException fırlatır

System.out.println(checkedList); // [string]


synchronizedMap(Map<K,V> m): Eşzamanlı olarak erişilebilen bir map döndürür.


java

Copy code

Map<String, Integer> map = new HashMap<>();

Map<String, Integer> syncMap = Collections.synchronizedMap(map);

syncMap.put("one", 1);

syncMap.put("two", 2);

System.out.println(syncMap); // {one=1, two=2}


synchronizedSet(Set<T> s): Eşzamanlı olarak erişilebilen bir set döndürür.


java

Copy code

Set<String> set = new HashSet<>();

Set<String> syncSet = Collections.synchronizedSet(set);

syncSet.add("one");

syncSet.add("two");

System.out.println(syncSet); // [one, two] (Sıralama değişebilir)


synchronizedList(List<T> list): Eşzamanlı olarak erişilebilen bir liste döndürür.


java

Copy code

List<String> list = new ArrayList<>();

List<String> syncList = Collections.synchronizedList(list);

syncList.add("one");

syncList.add("two");

System.out.println(syncList); // [one, two]


unmodifiableMap(Map<? extends K, ? extends V> m): Değiştirilemeyen bir map görünümü döndürür.


java

Copy code

Map<String, Integer> map = new HashMap<>();

map.put("one", 1);

Map<String, Integer> unmodifiableMap = Collections.unmodifiableMap(map);

System.out.println(unmodifiableMap); // {one=1}

// unmodifiableMap.put("two", 2); // Bu satır bir UnsupportedOperationException fırlatır


unmodifiableSet(Set<? extends T> s): Değiştirilemeyen bir set görünümü döndürür.


java

Copy code

Set<String> set = new HashSet<>(Arrays.asList("one", "two", "three"));

Set<String> unmodifiableSet = Collections.unmodifiableSet(set);

System.out.println(unmodifiableSet); // [one, two, three]

// unmodifiableSet.add("four"); // Bu satır bir UnsupportedOperationException fırlatır

 

unmodifiableList(List<? extends T> list): Değiştirilemeyen bir liste görünümü döndürür.


java

Copy code

List<String> list = new ArrayList<>(Arrays.asList("one", "two", "three"));

List<String> unmodifiableList = Collections.unmodifiableList(list);

System.out.println(unmodifiableList); // [one, two, three]

// unmodifiableList.add("four");

// Bu satır bir UnsupportedOperationException fırlatır

```


Java Collections Framework'ün sağladığı işlevler geniş bir yelpazeye yayılır. İşte bazı ek fonksiyonlar ve kullanım örnekleri:


synchronizedSortedSet(SortedSet<T> s): Eşzamanlı olarak erişilebilen bir sıralı set döndürür.


java

Copy code

SortedSet<String> sortedSet = new TreeSet<>();

sortedSet.add("one");

sortedSet.add("two");

SortedSet<String> syncSortedSet = Collections.synchronizedSortedSet(sortedSet);

System.out.println(syncSortedSet); // [one, two]


synchronizedSortedMap(SortedMap<K,V> m): Eşzamanlı olarak erişilebilen bir sıralı map döndürür.


java

Copy code

SortedMap<String, Integer> sortedMap = new TreeMap<>();

sortedMap.put("one", 1);

sortedMap.put("two", 2);

SortedMap<String, Integer> syncSortedMap = Collections.synchronizedSortedMap(sortedMap);

System.out.println(syncSortedMap); // {one=1, two=2}


unmodifiableSortedSet(SortedSet<T> s): Değiştirilemeyen bir sıralı set görünümü döndürür.


java

Copy code

SortedSet<String> sortedSet = new TreeSet<>(Arrays.asList("one", "two", "three"));

SortedSet<String> unmodifiableSortedSet = Collections.unmodifiableSortedSet(sortedSet);

System.out.println(unmodifiableSortedSet); // [one, two, three]

// unmodifiableSortedSet.add("four"); // Bu satır bir UnsupportedOperationException fırlatır


unmodifiableSortedMap(SortedMap<K,V> m): Değiştirilemeyen bir sıralı map görünümü döndürür.


java

Copy code

SortedMap<String, Integer> sortedMap = new TreeMap<>();

sortedMap.put("one", 1);

sortedMap.put("two", 2);

SortedMap<String, Integer> unmodifiableSortedMap = Collections.unmodifiableSortedMap(sortedMap);

System.out.println(unmodifiableSortedMap); // {one=1, two=2}

// unmodifiableSortedMap.put("three", 3); // Bu satır bir UnsupportedOperationException fırlatır

Bu örnekler, Java Collections sınıfının sağladığı işlevselliklerin yalnızca bir kısmını temsil eder. Bu fonksiyonlar, veri koleksiyonlarınızı daha güvenli, esnek ve verimli bir şekilde işlemenize yardımcı olabilir. Her birinin farklı senaryolarda nasıl kullanılacağını öğrenmek, Java'da daha etkili programlama yapmanıza olanak tanır.





Java^da Record yapısı, SSS ve Cevapları




Java'da record yapısı, Java 14'te tanıtılan ve Java 16 ile kalıcı bir özellik haline gelen bir veri taşıma nesnesidir. Bir record, yalnızca veri taşımak için kullanılan, sınırlı bir sayıda alanı (özellikleri) olan ve bu alanlara otomatik olarak uygulanan bir dizi yönteme (metod) sahip özel bir türdür. record'lar, sınıfların aksine, sadece veriyi tutmak ve bu veriye erişim sağlamak için kullanılırlar. İmmutable (değiştirilemez) nesneler oluşturmak için idealdirler.


record yapısı şu şekilde tanımlanır:


java

Copy code

record RecordName(Type1 fieldName1, Type2 fieldName2, Type3 fieldName3, ...) {

    // Additional methods and constructors

}

record kullanımının temel avantajları şunlardır:


Sözdizimi Kısalığı: recordlar, aynı verilere erişim için gerekli olan standart Java sınıflarına göre çok daha az kod gerektirir.

İmmutability: recordların tüm alanları final ve private'dır. Bu, oluşturulduktan sonra değiştirilemeyeceklerini garantiler.

Data odaklı: recordlar veri taşıma ve veriye erişim için tasarlanmıştır, bu nedenle veri modelleme ihtiyaçlarınız için mükemmeldirler.

Otomatik olarak uygulanan yöntemler: recordlar, equals(), hashCode(), ve toString() gibi yöntemleri otomatik olarak uygularlar, bu yüzden bu yöntemleri manuel olarak uygulamanıza gerek kalmaz.

Örnek bir record tanımı:


java

Copy code

record Person(String name, int age) {}

Bu tanım, Person adında bir record oluşturur ve bu record, String türünde bir name ve int türünde bir age alanına sahiptir. Java, bu record için otomatik olarak name() ve age() adında erişim yöntemleri, equals(), hashCode(), ve toString() yöntemlerini oluşturur.


recordlar, veri odaklı uygulamalar ve mikroservis mimarileri gibi alanlarda, nesne modellerinin basitleştirilmesi ve kodun daha anlaşılır hale getirilmesi için yaygın olarak kullanılmaktadır.


SSS ve Cevapları


SSS (Sıkça Sorulan Sorular) ve cevapları formatında bilgi sunmak, belirli konular hakkında hızlı ve etkili bir şekilde bilgi almanızı sağlar. Aşağıda, genel bir konu hakkında olası SSS örnekleri ve bu soruların cevapları yer almaktadır:


S1: Java'da record yapısının avantajı nedir?


C1: Java'da record yapısı, daha az kodla daha temiz ve daha okunabilir veri taşıma modelleri oluşturmayı sağlar. Ayrıca, recordlar otomatik olarak equals(), hashCode(), ve toString() yöntemlerini uygular, bu da hata yapma olasılığını azaltır ve kod tekrarını önler.


S2: recordlar neden immutabledır?


C2: recordlar, tanımlandıkları andan itibaren değiştirilemeyen (immutable) veri yapılarıdır. Bu, verilerin yanlışlıkla değiştirilmesini önler ve çoklu iş parçacığı ortamlarında güvenli kullanımı sağlar.


S3: Java'da bir record nasıl tanımlanır?


C3: Java'da bir record, aşağıdaki sözdizimi kullanılarak tanımlanır: record RecordName(Type1 fieldName1, Type2 fieldName2, ...) {}. Bu, veri taşımak için kullanılan, belirli alanlara sahip bir nesne oluşturur.


S4: Java'daki recordlar ve sınıflar arasındaki temel farklar nelerdir?


C4: Temel farklar, recordların immutability, sözdizimi kısalığı ve otomatik olarak uygulanan yöntemler gibi özelliklere sahip olmasıdır. Buna karşılık, sınıflar daha esnek olabilir ve duruma göre değiştirilebilir veri üyeleri içerebilir.


S5: Bir record içinde ek yöntemler tanımlayabilir miyim?


C5: Evet, bir record içinde ek yöntemler tanımlayabilirsiniz. Ancak, recordın alanları değiştirilemez olduğu için, bu yöntemler yalnızca veri okuma veya dönüştürme işlemleri yapmalıdır.


S6: recordlar nerede kullanılmalıdır?


C6: recordlar, veri taşımak, konfigürasyon verilerini yönetmek, JSON/XML dönüştürmeleri gibi işlemler ve mikroservisler arası iletişimde kullanılmak üzere mükemmeldir. İmmutability ve veri odaklı tasarımı nedeniyle, veri güvenliğini ve tutarlılığını sağlamada etkilidirler.

Java JDBC ile Elasticsearch'de SQL sorgusu yazabilir miyim?

Evet, Java JDBC kullanarak Elasticsearch'de SQL sorguları yazabilirsiniz.



Bunun için iki temel yöntem vardır:


1. Elasticsearch SQL Plugin:


Elasticsearch'e yüklenebilen bir plugindir.

SQL'e benzer bir dil kullanarak Elasticsearch sorguları oluşturmanıza imkan verir.

Plugin'in sunduğu özel fonksiyonlar ile Elasticsearch'e özgü işlemleri de gerçekleştirebilirsiniz.

Kurulum ve kullanım detayları için: https://www.elastic.co/elasticsearch/sql

2. JDBC Driver:


Elasticsearch'e JDBC ile bağlanmanızı sağlayan bir sürücü yazılımıdır.

SQL sorgularınızı JDBC API'si aracılığıyla çalıştırabilirsiniz.

Çeşitli JDBC driver seçenekleri mevcuttur:

JDBC for Elasticsearch: https://www.elastic.co/guide/en/elasticsearch/reference/current/sql-jdbc.html

Logstash JDBC Input Plugin: https://github.com/logstash-plugins/logstash-input-jdbc

Her iki yöntemin de kendine özgü avantajları ve dezavantajları vardır:


Elasticsearch SQL Plugin:


Avantajları:


Kullanımı daha kolay, SQL'e daha yakın bir dil sunar.

Elasticsearch'e özgü fonksiyonlara erişim sağlar.

Dezavantajları:


Daha az esneklik sunar.

Karmaşık sorgularda performans sorunları yaşayabilir.

JDBC Driver:


Avantajları:


Daha fazla esneklik sunar.

Karmaşık sorguları daha verimli çalıştırabilir.

Dezavantajları:


Kullanımı daha karmaşıktır.

Elasticsearch'e özgü fonksiyonlara erişim için ek kodlamaya ihtiyaç duyulabilir.

Hangi yöntemi seçmeniz gerektiği:


Basit sorgular ve hızlı başlangıç için: Elasticsearch SQL Plugin

Karmaşık sorgular ve daha fazla esneklik için: JDBC Driver

Örnek:


Aşağıdaki kod, JDBC for Elasticsearch kullanarak Elasticsearch'e bir SQL sorgusu gönderir:


Java

import com.amazon.elasticsearch.driver.client.JestClient;

import com.amazon.elasticsearch.driver.geo.GeoPoint;

import com.amazon.elasticsearch.driver.indices.Index;

import com.amazon.elasticsearch.driver.indices.Mapping;

import com.amazon.elasticsearch.driver.query.MatchAllQuery;

import com.amazon.elasticsearch.driver.query.Query;

import com.amazon.elasticsearch.driver.search.SearchRequest;

import com.amazon.elasticsearch.driver.search.SearchResponse;


public class Example {


    public static void main(String[] args) {

        JestClient client = new JestClient("localhost", 9200);


        // Döküman ekleme

        Index index = new Index("my-index");

        Mapping mapping = new Mapping("my-type");

        mapping.addField("name", "text");

        mapping.addField("location", "geo_point");


        client.createIndex(index, mapping);


        // SQL sorgusu oluşturma

        String sql = "SELECT * FROM my-index WHERE location NEAR '41.999999,28.999999'";


        // JDBC ile sorguyu çalıştırma

        SearchRequest request = new SearchRequest(index);

        Query query = new MatchAllQuery();

        request.setQuery(query);


        SearchResponse response = client.executeSearch(request);


        // Sonuçları işleme

        for (SearchResult hit : response.getHits()) {

            System.out.println(hit.getSource().get("name"));

        }

    }

}

Kodu dikkatli kullanın.

Bu örnekte, "my-index" adlı bir indekse "name" ve "location" alanlarına sahip bir döküman eklenir. Daha sonra, "location" alanı belirli bir koordinata yakın olan tüm dökümanları bulmak için bir SQL sorgusu çalıştırılır.


Not: Yukarıdaki kod sadece basit bir örnektir. Daha karmaşık sorgular için JDBC driver'ın dokümantasyonuna bakabilirsiniz.

Unix bir makinada çalışan, java uygulamamda birden fazla threadlerim var. Memory ve process yönetimi nasıl olur?


Görseldeki her süreç, bir Java uygulamasını temsil ediyor olabilir, ancak bu kesin olarak belirtilmemişse sadece varsayımsal bir yorum olur. Genellikle Java'da, bir süreç bir JVM örneğini temsil eder ve her JVM örneği içerisinde çalışan birden fazla thread olabilir. Görselde gösterilen her bir sürecin bağımsız bir Java uygulaması olduğunu varsayabiliriz, çünkü her biri kendi içinde izole edilmiş thread'lere sahip.Java uygulamanızda birden fazla thread kullanıldığında, memory (bellek) ve process (işlem) yönetimi konuları önem kazanır. Unix tabanlı sistemlerde, Java uygulamanızın performansını ve stabilitesini etkileyebilecek birkaç önemli konu vardır:


Memory Yönetimi

Heap Memory: Java'da tüm nesneler heap memory üzerinde yaşar. Birden fazla thread aynı heap alanını paylaşır. Yani, bir thread tarafından oluşturulan nesnelere diğer thread'ler de erişebilir. Bu nedenle, heap memory boyutunun uygun şekilde ayarlanması gerekir. -Xms ve -Xmx JVM argümanları ile başlangıç ve maksimum heap boyutları ayarlanabilir.


Stack Memory: Her thread için ayrı bir stack memory bulunur. Bir thread'in fonksiyon çağrıları ve yerel değişkenleri bu alanda saklanır. Eğer uygulamanız derin fonksiyon çağrıları yapıyorsa veya çok sayıda yerel değişken kullanıyorsa, stack boyutu önem kazanır. -Xss argümanı ile thread başına stack boyutu ayarlanabilir.


Garbage Collection (GC): GC, kullanılmayan nesneleri heap'ten temizleyerek memory'i verimli bir şekilde yönetir. Birden fazla thread'in çalıştığı bir uygulamada GC'nin etkinliği, uygulamanın performansını doğrudan etkileyebilir. GC işlemleri için farklı algoritmalar ve ayarlar mevcuttur (-XX:+UseG1GC, -XX:+UseParallelGC gibi).


Process Yönetimi

Thread Management: Java, işletim sistemi seviyesinde native thread'leri kullanır. Unix sistemlerde, her Java thread'i genellikle işletim sistemi tarafından bir hafif işlem (lightweight process) olarak görülür. Bu, Java uygulamanızın thread'lerinin işletim sistemi kaynaklarını doğrudan etkileyebileceği anlamına gelir.


Synchronization: Birden fazla thread'in aynı kaynaklara (örneğin, değişkenlere veya nesnelere) erişimi söz konusu olduğunda, uygun senkronizasyon mekanizmalarının kullanılması gerekir. Bu, synchronized blokları, lock'lar veya diğer concurrency mekanizmaları aracılığıyla sağlanabilir. Uygun senkronizasyon olmadan, race condition'lar, deadlocks ve diğer senkronizasyon sorunları yaşanabilir.


Resource Management: Açık dosya tanıtıcıları, ağ bağlantıları ve diğer sistem kaynakları dikkatli bir şekilde yönetilmelidir. Unix sistemlerde, her process'in kullanabileceği maksimum dosya tanıtıcı sayısı gibi kaynaklar sınırlıdır. Bu kaynakların yönetimi, özellikle yüksek sayıda thread kullanıldığında önemli hale gelir.


Unix tabanlı sistemlerde Java uygulamanızın verimli çalışabilmesi için bu faktörleri göz önünde bulundurmanız önemlidir. JVM ayarlarını, uygulamanızın ihtiyaçlarına göre özelleştirmek, uygun senkronizasyon ve kaynak yönetimi tekniklerini kullanmak, uygulamanızın performansını ve stabilitesini artırabilir.


Stack Memory: Her thread için ayrı bir stack memory bulunur. Bir thread'in fonksiyon çağrıları ve yerel değişkenleri bu alanda saklanır. Eğer uygulamanız derin fonksiyon çağrıları yapıyorsa veya çok sayıda yerel değişken kullanıyorsa, stack boyutu önem kazanır. -Xss argümanı ile thread başına stack boyutu ayarlanabilir.


Evet, doğru. Java'da her thread için ayrı bir stack memory (yığın belleği) bulunur ve bu, fonksiyon çağrıları (method invocations) ve yerel değişkenler için kullanılır. Bu özellik, Java'nın thread başına izolasyon sağlamasına ve bir thread'in stack memory'sinin başka bir thread tarafından doğrudan etkilenmemesine olanak tanır. Stack memory'nin boyutu, bir thread'in ne kadar derin fonksiyon çağrıları yapabileceğini ve ne kadar çok yerel değişken saklayabileceğini belirler.


Stack Memory Boyutunun Ayarlanması

-Xss JVM (Java Virtual Machine) argümanı, Java uygulamanızı başlatırken her thread için ayrılan stack memory boyutunu ayarlamanıza olanak tanır. Örneğin, her thread için stack boyutunu 512 kilobyte olarak ayarlamak istiyorsanız, Java uygulamanızı şu şekilde başlatabilirsiniz:


shell

Copy code

java -Xss512k MyClass

Burada 512k her thread için ayrılan stack boyutunu 512 kilobyte olarak belirler. Bu ayar, derin fonksiyon çağrıları yapan veya çok sayıda yerel değişken kullanan uygulamalar için önemlidir. Yeterli stack memory'si olmaması, StackOverflowError gibi hatalara yol açabilir.


Dikkat Edilmesi Gerekenler

Performans ve Kaynak Kullanımı: Her thread için çok büyük bir stack boyutu ayarlamak, kullanılmayan bellek alanına neden olabilir ve sistem kaynaklarını gereksiz yere tüketebilir. Bu nedenle, ihtiyacınıza uygun bir değer seçmek önemlidir.


Sistem Sınırları: İşletim sisteminizin ve donanımınızın desteklediği maksimum stack boyutu ve thread sayısı gibi sınırlamaları da göz önünde bulundurmalısınız. Çok sayıda thread kullanıyorsanız, her biri için ayrılan stack boyutunun toplamı önemli bir bellek kullanımına yol açabilir.


Uygulama Senaryoları: Uygulamanızın gereksinimlerine bağlı olarak, bazı durumlarda daha büyük bir stack boyutuna ihtiyaç duyabilirsiniz. Örneğin, çok derin rekürsif fonksiyon çağrıları yapıyorsanız veya karmaşık algoritmalar uyguluyorsanız, stack boyutunu artırmak gerekebilir.


-Xss parametresi ile ayarlanan stack boyutu, uygulamanızın gereksinimlerine ve kullanılabilir sistem kaynaklarına göre dikkatlice seçilmelidir. Bu ayar, uygulamanızın performansı ve stabilitesi üzerinde doğrudan etkili olabilir.


Thread Management: Java, işletim sistemi seviyesinde native thread'leri kullanır. Unix sistemlerde, her Java thread'i genellikle işletim sistemi tarafından bir hafif işlem (lightweight process) olarak görülür. Bu, Java uygulamanızın thread'lerinin işletim sistemi kaynaklarını doğrudan etkileyebileceği anlamına gelir.


Evet, bu açıklama doğru bir şekilde Java'nın thread yönetimini ve işletim sistemiyle olan etkileşimini özetlemektedir. Java'da thread'ler, altında yatan işletim sisteminin thread mekanizmalarını kullanarak gerçekleştirilir. Java Virtual Machine (JVM) üzerinde çalışan Java thread'leri, çoğu modern işletim sisteminde native thread'ler olarak uygulanır. Bu, Java thread'lerinin doğrudan işletim sistemi tarafından yönetilen hafif işlemler (lightweight processes) olmasını sağlar.


Thread'lerin İşletim Sistemi Kaynakları Üzerindeki Etkisi

Kaynak Kullanımı: Her Java thread'i, kendi stack memory'sine sahip olduğu gibi, işletim sistemi kaynaklarını da kullanır. Bu kaynaklar CPU zamanı, bellek, dosya tanıtıcıları ve ağ bağlantıları olabilir. Java uygulamanız çok sayıda thread oluşturduğunda, bu kaynakların tüketimi artar.


Planlama ve Öncelikler: İşletim sistemi, tüm thread'leri planlar ve CPU zamanını bunlar arasında paylaştırır. Java uygulamanızdaki thread'lere öncelik atanabilir, ve bu öncelikler altında yatan işletim sistemi tarafından dikkate alınarak işlem zamanı atanır. Ancak, Java'dan atanan önceliklerin işletim sistemi tarafından nasıl yorumlandığı platforma bağlıdır.


Eşzamanlılık ve Senkronizasyon: Java'nın eşzamanlılık kütüphaneleri, işletim sisteminin eşzamanlılık mekanizmaları üzerine inşa edilmiştir. Bu, lock'lar, semaforlar ve diğer senkronizasyon araçlarının, işletim sistemi seviyesindeki karşılıklarını kullanması anlamına gelir. Bu araçlar, thread'ler arasındaki erişim kontrolünü sağlar ve yarış durumları (race conditions) gibi sorunları önlemeye yardımcı olur.


İşletim Sistemi ve Java Arasındaki Etkileşim

Java'nın platform bağımsızlığı, JVM'in altında yatan işletim sistemiyle olan etkileşimini gizler. Bu, Java uygulamalarının farklı işletim sistemlerinde tutarlı bir şekilde çalışabilmesini sağlar. Ancak, işletim sistemi kaynaklarının kullanımı ve thread yönetimi gibi konularda, işletim sisteminin özellikleri ve sınırlamaları göz önünde bulundurulmalıdır.


Örneğin, bir Unix sisteminde, işletim sistemi kaynaklarının sınırlı olabileceği ve çok sayıda thread'in sistem performansı üzerinde olumsuz etkiler yaratabileceği unutulmamalıdır. Ayrıca, işletim sistemi düzeyindeki thread'ler arasındaki bağlam değişiklikleri (context switches) maliyetli olabilir, bu yüzden thread sayısının ve thread oluşturma sıklığının dikkatli bir şekilde yönetilmesi önemlidir.


Java'nın thread modeli ve işletim sistemleriyle olan etkileşimi, geliştiricilere güçlü bir eşzamanlılık modeli sunarken, aynı zamanda kaynak kullanımı ve performans üzerinde dikkatli düşünmeyi gerektirir.


User

Javadaki her thread için işletim sisteminde karşılık gelen bir thread mi oluşturulur?

ChatGPT

Java'daki thread modeli ve işletim sistemleri arasındaki ilişki, JVM'nin ve işletim sisteminin belirli bir sürümüne bağlı olarak değişebilir. Genel olarak, modern Java Virtual Machine (JVM) sürümleri ve işletim sistemleri, Java thread'lerini işletim sistemi düzeyindeki native thread'lerle eşleştirme eğilimindedir. Bu, Java'da oluşturulan her thread için işletim sistemi düzeyinde bir karşılığın oluştuğu anlamına gelir. Ancak, bu durum her zaman kesin değildir ve JVM'nin thread modeli ile işletim sistemi arasındaki ilişkiyi etkileyebilecek bazı faktörler vardır:


1:1 Modeli (Native Thread Modeli)

Bu modelde, Java tarafından oluşturulan her thread için işletim sistemi seviyesinde doğrudan bir karşılık vardır. Bu, Java thread'lerinin işletim sisteminin thread planlayıcısı tarafından yönetildiği ve işletim sisteminin thread yönetimi, senkronizasyon ve diğer eşzamanlılık özelliklerine doğrudan erişim sağladığı anlamına gelir. Modern Unix, Linux, Windows ve diğer işletim sistemlerinde bu model yaygındır.


N:M Modeli (Green Thread Modeli)

Bu model, geçmişte bazı JVM uygulamalarında kullanılmıştır ve Java thread'lerinin doğrudan işletim sistemi thread'leriyle eşlenmediği bir modeldir. Bunun yerine, JVM içinde bir veya daha fazla native thread üzerinde birden fazla Java thread'i çalıştırılabilir. Bu model, işletim sisteminin thread desteği zayıf olan eski sistemlerde veya işletim sistemi kaynaklarının daha verimli kullanılmasını amaçlayan durumlarda kullanılmıştır. Ancak, modern JVM sürümlerinde bu modelin kullanımı azalmıştır ve çoğu durumda tercih edilen yaklaşım 1:1 modelidir.


Etkileri ve Tercihler

Performans ve Ölçeklenebilirlik: 1:1 modeli, işletim sistemi düzeyindeki eşzamanlılık ve çok çekirdekli işlemcilerin avantajlarından yararlanmayı sağlar. Ancak, çok sayıda thread oluşturmak işletim sistemi kaynaklarını önemli ölçüde tüketebilir ve bağlam değişikliklerinin maliyeti artabilir.


Uyumluluk ve Taşınabilirlik: Java'nın platform bağımsız doğası, uygulamaların farklı işletim sistemlerinde tutarlı bir şekilde çalışmasını sağlar. Ancak, işletim sistemi düzeyindeki thread'lerin davranışı platforma bağlı olabileceği için, çoklu-threading ile ilgili performans ve davranış farklılıkları yaşanabilir.


Sonuç olarak, modern Java uygulamalarında, Java tarafından oluşturulan her thread genellikle işletim sistemi seviyesinde bir karşılık bulur ve bu, 1:1 modeli ile uyumlu bir yaklaşımı temsil eder. Ancak, JVM ve işletim sistemi arasındaki etkileşim, uygulamanın çalıştığı özel platforma ve JVM sürümüne bağlı olarak farklılık gösterebilir.

Örnek bir Java Hello World Kodu ve Assembly Kodu karşılığı



Java dili yüksek seviye, nesne yönelimli bir programlama dilidir, oysa Assembly dili düşük seviyeli, makineye yakın bir dildir. Aynı işlevi gerçekleştiren Java kodu ve onun Assembly dilindeki karşılığını göstermek oldukça karmaşık olabilir çünkü bu iki dil arasındaki farklar çok büyüktür. Ancak, basit bir örnek üzerinden gidelim.


Java'da yazılmış basit bir "Merhaba Dünya" programı şu şekilde olabilir:



public class HelloWorld {

    public static void main(String[] args) {

        System.out.println("Merhaba Dünya");

    }

}

Bu Java kodunun Assembly dilinde bir karşılığı oluşturmak için, öncelikle hangi Assembly dilini (x86, ARM, vb.) ve işletim sistemini (Windows, Linux, vb.) kullanacağımızı belirlememiz gerekir. Farklı Assembly dilleri ve işletim sistemleri için yazım şekilleri değişiklik gösterebilir.


Örnek olarak, x86 Assembly dilinde ve Linux işletim sistemi için basit bir "Merhaba Dünya" programı aşağıdaki gibi olabilir:


section .data

    msg db 'Merhaba Dünya',0xa

    len equ $ - msg


section .text

    global _start


_start:

    mov eax, 4          ; syscall number for sys_write

    mov ebx, 1          ; file descriptor 1 is stdout

    mov ecx, msg        ; message to write

    mov edx, len        ; message length

    int 0x80            ; call kernel


    mov eax, 1          ; syscall number for sys_exit

    xor ebx, ebx        ; return 0 status

    int 0x80            ; call kernel

Bu Assembly kodu, basit bir "Merhaba Dünya" mesajını terminal üzerinde gösterir. Ancak, bu kodun Java koduyla aynı işlevi gerçekleştirdiğini söylemek zor çünkü Assembly, donanıma çok daha yakın bir düzeyde çalışır ve işletim sistemiyle doğrudan etkileşime girer. Java ise JVM (Java Sanal Makinesi) üzerinde çalışır ve birçok donanım ve işletim sistemi detayından soyutlanmıştır.


Linux işletim sistemi üzerinde çalışacak şekilde tasarlanmıştır. Her satırın ne yaptığını açıklayayım:


section .data


Bu satır, veri bölümünün başlangıcını işaret eder. Burada sabit veriler ve değişkenler tanımlanır.


msg db 'Merhaba Dünya',0xa


msg adında bir değişken tanımlar ve bu değişkene 'Merhaba Dünya' stringini ve bir satır sonu karakteri (0xa, yani newline) atar.


len equ $ - msg


len adında bir sabit tanımlar. Bu sabit, msg değişkeninin uzunluğunu hesaplar. $ işareti geçerli adresi, msg ise msg değişkeninin başlangıç adresini temsil eder. Bu fark, mesajın uzunluğunu verir.


section .text


Bu, programın kod bölümünün başlangıcını işaret eder. Burada programın çalıştırılabilir kodları yer alır.


global _start


Bu satır, _start etiketinin diğer dosyalar tarafından görülebilir olduğunu belirtir. Bu, programın giriş noktasını işaret eder.


_start:


Bu, programın başladığı yerdir.


mov eax, 4


EAX kaydedicisine 4 değerini yükler. Bu, sys_write sistem çağrısının syscall numarasıdır.


mov ebx, 1


EBX kaydedicisine 1 değerini yükler. Bu, standart çıktı dosya tanıtıcısını (stdout) temsil eder.


mov ecx, msg


ECX kaydedicisine msg değişkeninin adresini yükler. Bu, yazılacak mesajı gösterir.


mov edx, len


EDX kaydedicisine len sabitini yükler. Bu, yazılacak mesajın uzunluğunu belirtir.


int 0x80


Linux kerneline bir kesme çağrısı yapar. Bu çağrı, EAX'de belirtilen sistem çağrısını (bu durumda sys_write) gerçekleştirir.


mov eax, 1


EAX kaydedicisine 1 değerini yükler. Bu, sys_exit sistem çağrısının syscall numarasıdır.


xor ebx, ebx


EBX kaydedicisini sıfırlar. Programın çıkış durumu olarak 0 döndürülmesini sağlar.


int 0x80


Yine Linux kerneline bir kesme çağrısı yapar ve EAX'de belirtilen sistem çağrısını (bu durumda sys_exit) gerçekleştirir.

Bu kod, temel bir Assembly programının nasıl yazılacağı ve basit sistem çağrılarının nasıl kullanılacağı konusunda iyi bir örnektir.


Makina diline de çevirip yorumlar mısın?


Genel bir fikir vermek için kodunuzu makine dilinde nasıl temsil edilebileceği hakkında bazı yorumlar yapabilirim:


mov eax, 4


Bu komut, eax kaydedicisine 4 değerini yerleştirir. Makine dilinde, mov komutu genellikle kaynağı ve hedefi belirten belirli kodlarla temsil edilir. Örneğin, B8 04 00 00 00 gibi bir dizi bayt olabilir (bu sadece bir örnektir).

mov ebx, 1


Benzer şekilde, bu mov komutu ebx kaydedicisine 1 değerini atar. Makine dilinde bu, BB 01 00 00 00 gibi bir şey olabilir.

mov ecx, msg


Bu, ecx kaydedicisine msg değişkeninin adresini yükler. Makine dilindeki temsili, msg değişkeninin gerçek adresine bağlı olacaktır.

mov edx, len


edx kaydedicisine len değerini yerleştirir. Makine dilindeki temsili, len değerinin boyutuna bağlı olacaktır.

int 0x80


Bu, bir kesme çağrısıdır ve genellikle CD 80 gibi bir bayt dizisiyle temsil edilir.

xor ebx, ebx


Bu, ebx kaydedicisini sıfırlar. Makine dilinde, bu genellikle 31 DB gibi bir bayt dizisiyle temsil edilir.

Diğer mov ve int komutları


Benzer şekilde, bu komutlar da kendi makine dilindeki karşılıklarıyla temsil edilecektir.

Makine dilinde her bir komut, işlemcinin anlayabileceği spesifik bayt dizileriyle temsil edilir. Bu bayt dizileri, kullanılan işlemci mimarisine ve komutların belirli ayrıntılarına (kaynak, hedef, değerler vb.) bağlı olarak değişir. ​

Java'da String Pool Konsepti

Java'da String Pool Konsepti

    

    Java programlama dilinde String veri tipi, çift tırnak içerisine yazılmış karakterler dizisi olarak tanımlanır. Aşağıda en basit haliyle bir String tanımlaması yapılmıştır.

String name = "Muhammet";

    Yukarıdaki tanımlama String Literals olarak adlandırılmaktadır. String literals, bir programcının belirli bir değeri ifade etmek amacıyla yazdığı sabit karakter dizileridir.

    Yukarıda String türünde tanımlanan ve name olarak adlandırılan nesne elbette primitive tiplerden(int,byte,long vb.) farklı olarak Stack yerine Heap bölgesinde tutulmaktadır, dolayısıyla bir referansa sahiptir. Yani derleyici bu satırı çalıştırdığında Heap bölgesinde “Muhammet” değerini tutan bir obje oluşturur ve “name” isimli değişkene bunun referansını verir.

    Peki devam eden kısımda aşağıdaki gibi aynı değere sahip ikinci bir değişken tanımlaması yapsaydık bu iki nesnenin referansı aynı mı olurdu? Bunu anlamak için referanslarının hashCode değerlerini ekrana yazdıralım.

String name = "Muhammet";
String name2 = "Muhammet";

System.out.println(System.identityHashCode(name));
System.out.println(System.identityHashCode(name2));

//Output
//1705736037
//1705736037

    Evet! Görüldüğü üzere her iki nesnenin de referanslarının hashCode değerlerini ekrana yazdırdığımızda aynı değeri yazdığını görüyoruz. Yukarıdaki örnekte iki tane değil bir milyon tane değişken de tanımlasaydık bunların tamamının referansı aynı olacaktı.

    Buradan anlıyoruz ki biz bir milyon tane değişken tanımlasak da JVM bunlara karşılık Heap bölgesinde yalnızca bir tane obje tanımlıyor.

Peki Neden?

    Tabii ki amaç bellek optimizasyonu. Varsayılan olarak literals kullanarak bir String objesi oluşturduğunuzda JVM oluşturmak istediğiniz değerin varlığını String Pool yapısı içerisinde kontrol eder. Eğer burada zaten bu değer mevcut ise, yeni bir tane oluşturmak yerine geriye bu objenin referansını döner. Bu sayede tekrar eden verinin önüne geçilir.

Nedir bu String Pool?

    Makalemizin başlangıcındaki görselden görüldüğü üzere JVM Heap bellek kısmı içerisinde String Pool adı verilen bir alan vardır. Bu alan aynı zamanda String Constant Pool veya String Intern Pool olarak da adlandırılır.

    Siz bir String oluşturduğunuzda JVM varsayılan olarak önce bu alanı kontrol eder. Eğer bu alanda, oluşturduğunuz String değişken içerisindeki değer zaten daha önce tanımlanmış ise onun referansı değişkeninize atanır. Eğer öncesinde böyle bir değer String Pool içerisinde tanımlanmamış ise String Pool içerisinde bu değer tanımlanır ve değişkeninize atanır.

    Bundan sonra oluşturacağınız tüm String değişkenlerin değerleri bu alandan gelir veya bu alan içerisine tanımlanırlar. Bu sayede tekrar eden verinin önüne geçilmiş olur ve bellek kullanımı önemli ölçüde azaltılmış olur.

Peki String Pool Dışında String Tanımlamak İstersek?

    String Pool içerisinde işleri yürütmenin getirdiği bellek kullanımında tasarruf avantajının yanısıra her yeni String değişken oluşturduğunuzda bu alanın baştan sonra kontrol edilmesi gibi bir search işlemi gerçekleşir. Kimi zaman bellekten tasarruf etmek yerine buradaki işlem’in gecikmesinden, yükünden kaçınmak isteyebiliriz.

    Böyle durumlarda String Pool dışında, doğrudan Heap içerisinde String değişkenlerimizi tanımlamak, yönetmek isteyebiliriz. Bunun için tek yapmamız gereken tanımlama yaparken new anahtar kelimesini kullanmak.

String name = "Muhammet";
String name2 = "Muhammet";
String name3 = new String("Muhammet");

System.out.println(System.identityHashCode(name));
System.out.println(System.identityHashCode(name2));
System.out.println(System.identityHashCode(name3));

//Output
//1705736037
//1705736037
//455659002

    Yukarıdaki örnekte görüldüğü üzere new anahtar kelimesi kullanılarak String değişken tanımlandığında, farklı bir referansa sahip String Pool dışında tanımlamış oluyoruz.

String name = "Muhammet";
String name2 = "Muhammet";
String name3 = new String("Muhammet");

System.out.println(name == name2);
System.out.println(name == name3);
System.out.println(name.equals(name3));

//Output
//true
//false
//true

    Bu değişkenleri “==” operatörü kullanarak karşılaştırdığımızda, String Pool dışında olan ile içinde olan iki farklı değişken için sonuç false dönerken, String Pool içerisinde olan iki farklı değişken için sonuç true dönüyor.

    Bunun sebebi == operatörü kullanarak yapılan karşılaştırmalar değerler üzerinden değil referanslar üzerinden yapılır. Dolayısıyla String Pool içerisindeki aynı değere sahip değişkenlerin referansı aynı iken, new anahtar kelimesi ile tanımlanan değişkenin referansı farklı.

    Fakat referansları üzerinden değil değerleri üzerinden karşılaştırmak istersek de equals metodunu kullabiliriz.

intern() Fonksiyonu

String name4 = new String("Java");
String name5 = name4;

System.out.println(System.identityHashCode(name4));
System.out.println(System.identityHashCode(name5));

//Output
//250421012
//250421012

    Yine kodlar üzerinden ilerleyelim. Yukarıdaki örnekte name5 isimli değişkeni name4 değişkeninden türetiyoruz. Dolayısıyla referansları aynı. Fakat String Pool içerisine alınmıyorlar. Çünkü Heap üzerinde yaratıldı, Heap üzerinden referans alındı.

    Fakat bunun yerine oluşturacağımız yeni nesneyi String Pool içerisine koymak istiyor olabiliriz. Bu durumda .intern() fonksiyonu devreye giriyor.

String name4 = new String("Java");
String name5 = name4;
String name6 = name4.intern();
String name7 = "Java";

System.out.println(System.identityHashCode(name4));
System.out.println(System.identityHashCode(name5));
System.out.println(System.identityHashCode(name6));
System.out.println(System.identityHashCode(name7));

//Output
//250421012
//250421012
//1915318863
//1915318863

    Yukarıda “name6” isimli değişkeni oluştururken name4 değişkenini kullandık. Bu değişken String Pool’da değil, Heap üzerinde kendi başına bulunuyordu. Fakat bundan bir değişken oluştururken .intern() metodunu kullanarak oluşturduk. Bu metod sayesinde eğer String Pool’da böyle bir değer yoksa oluştur ve String Pool’a ekle demiş olduk.

    Devamında “Java” değerine sahip bir String değişkeni String literals kullanarak tanımladığımızda referansının String Pool’dan geldiğini görebiliyoruz.

Gelelim String Pool kavramının artı ve eksilerine;

Artılar

  • Performans. JVM yeni bir String objesi yaratmak yerine varolan üzerinden referans aldığı için String işlemleri daha hızlıdır.

  • Bellek Kullanımı. String Pool içerisinde bulunan tek bir String’i referansı üzerinden sürekli paylaştığınız için sürekli yeni String objeleri oluşturmaz ve bellek kullanımını önemli ölçüde azaltabilirsiniz.


Eksiler

  • Performans. Evet artılarda olan madde burada da var. Bunun sebebi yeni bir String değişken oluşturduğunuzda bellekte direkt olarak yenisini oluşturmak yerine, String Pool içerisinde arama işlemi yaptırmak zorunda kalırsınız. Böyle bir değer varsa yenisini oluşturmayalım derken eğer yüksek sayıda String objeleri ile çalışıyorsanız JVM kimi zaman koskoca bir havuzu taramak zorunda kalabilir. Ve bunu her seferinde yapacağı için eğer yüksek sayıda String objesi ile çalışıyorsanız String Pool yapısı size faydadan çok zarar getirebilir, dikkatli olmak zorundasınız.


Rastgele İçerik

© tüm hakları saklıdır
made with by templateszoo