6 Mayıs 2024 Pazartesi

Virtual Threads - Thread Pinning

Thread Pinning 
Virtual Threads için JDK'daki bir çok kod baştan yazılmış. Böylece thread unloading işlemi yapılabiliyor.  Ancak bir kaç işlemde istisna var. Buna Thread Pinning deniliyor

1. Object.wait()
2. synchronized blok içinde
3. native metod çalıştırırken
4. UDP Sockets
5. Files & DNS

Açıklaması şöyle
Pinning describes the condition where a virtual thread, which maps the platform thread, is stuck to the carrier thread. It means that the virtual thread can’t be unmounted from the carrier threads because the state of it can’t be stored in the heap memory. The pinned thread prevents others from utilizing the same platform thread.
1. synchronized Thread Pinning
Açıklaması şöyle
Only one thread can enter it at a time. The other threads attempting to enter will be blocked until the current (running) thread exits. They would need an uninterrupted access to shared resources to prevent race conditions as well as an accurate state of the data.
Örnek
Şu kod carrier thread'i bloke eder
var e = Executors.newVirtualThreadPerTaskExecutor();
for (int i = 0; i < 1000; i++) {
    e.submit(() -> { new Test().test(); });
}
e.shutdown();
e.awaitTermination(1, TimeUnit.DAYS);

class Test {
  synchronized void test() {
    sleep(4000);
  }
}
synchronized yerine  ReentrantLock kullanılır. Şöyle yaparız
var e = Executors.newVirtualThreadPerTaskExecutor();
for (int i = 0; i < 1000; i++) {
    e.submit(() -> { new Test().test(); });
}
e.shutdown();
e.awaitTermination(1, TimeUnit.DAYS);

class Test {
  private ReentrantLock lock = new ReentrantLock();
  void test() {
    lock.tryLock();
    try {
      sleep(4000);
    } finally {
      lock.unlock();
    }
  }
}
MySQL-J JDBC sürücüsündeki bir açıklama şöyle
Synchronized blocks in the Connector/J code were replaced with ReentrantLocks. This allows carrier threads to unmount virtual threads when they are waiting on IO operations, making Connector/J virtual-thread friendly. Thanks to Bart De Neuter for contributing to this patch. ”

2. native method Thread Pinning
Açıklaması şöyle
This method lets you use code from other languages into your JAVA project, like C or C++. Native methods are invoked within the JAVA virtual machine but executed outside its control.
3. Sockets Thread Pinning
TCP socketlerini okurken Virtual Threads bloke olmuyor, ama UDP socketlerinde oluyor. Açıklaması şöyle
However, not all Java constructs have been retrofitted that way. Such operations include synchronized methods and code blocks. Using them causes the virtual thread to become pinned to the carrier thread. When a thread is pinned, blocking operations will block the underlying carrier thread-precisely as it would happen in pre-Loom times.
Eğer carrier therad'in bloke olma durumu varsa, virtual thread sayısı artırılır. En fazla kaç thread olabileceği  jdk.virtualThreadScheduler.maxPoolSize ile atanabilir

pinned thread Tracing
Açıklaması şöyle
Use the following JVM parameters as options to trace the pinned thread

-Djdk.tracePinnedThreads=full Prints a complete stack trace when a thread jams while pinned, highlighting native frames and frames holding monitors.

-Djdk.tracePinnedThreads=short Limits the output to just the problematic frames.

10 Mart 2024 Pazar

OpenRewrite

Giriş
OpenRewrite bir static kod analiz aracı. Diğer araçlardan farklı olarak sadece rapor üretmiyor aynı zamanda kodu da değiştirebiliyor.

1. dryRun Goal
target/rewrite dizini altında bir patch dosyası oluşturur

2. run Goal
Kodları direkt değiştirir

3. Recipe Listesi

3.1 CommonStaticAnalysis Recipe
Sanırım en işe yarayan recipe'lerden bir tanesi. Bur recipe ile yapılabilecek işlerin listesi burada

Benim hazelcast kodunda çalıştırdıklarım şöyle
  1. org.openrewrite.staticanalysis.UseDiamondOperator
  2. org.openrewrite.staticanalysis.UnncessaryThrows
  3. org.openrewrite.staticanalysis.NoRedundantJumpStatements
  4. org.openrewrite.staticanalysis.NestedEnumsAreNotStatic
  5. org.openrewrite.staticanalysis.RemoveRedundantTypeCast
  6. org.openrewrite.staticanalysis.LambdaBlockToExpression. EE için koşmadım
  7. org.openrewrite.staticanalysis.UnnecessaryExplicitTypeArguments
  8. org.openrewrite.staticanalysis.SimplifyTernaryRecipes
  9. org.openrewrite.staticanalysis.ReplaceRedundantFormatWithPrintf
  10. org.openrewrite.staticanalysis.InstanceOfPatternMatch.  EE için koşmadım. OS için yarım koştum
  11. org.openrewrite.staticanalysis.JavaApiBestPractices
  12. org.openrewrite.staticanalysis.PrimitiveWrapperClassConstructorToValueOf
  13. org.openrewrite.staticanalysis.NoPrimitiveWrappersForToStringOrCompareTo
  14. org.openrewrite.staticanalysis.UseMapContainsKey

Örnek
Şöyle yaparız
<plugin>
  <groupId>org.openrewrite.maven</groupId>
  <artifactId>rewrite-maven-plugin</artifactId>
  <version>5.23.1</version>
  <configuration>
    <activeRecipes>
      <recipe>org.openrewrite.staticanalysis.CommonStaticAnalysis</recipe>
    </activeRecipes>
  </configuration>
  <dependencies>
    <dependency>
      <groupId>org.openrewrite.recipe</groupId>
      <artifactId>rewrite-static-analysis</artifactId>
      <version>1.3.1</version>
    </dependency>
  </dependencies>
</plugin>
Eğer proje çok büyükse sadece bazı şeyleri çalıştırmak için proje kök dizininde bir tane rewrite.yml dosyası oluştururuz.  Şöyle yaparız. Eğer proje multi-module ise yine en tepedeki dizine koymak lazım
---
type: specs.openrewrite.org/v1beta/recipe
name: orcun.CommonStaticAnalysis
displayName: Common static analysis issues
description: Resolve common static analysis issues discovered through 3rd party tools.
recipeList:
  - org.openrewrite.staticanalysis.UseDiamondOperator
pom.xml şöyle olur.
<plugin>
  <groupId>org.openrewrite.maven</groupId>
  <artifactId>rewrite-maven-plugin</artifactId>
  <version>5.23.1</version>
  <configuration>
    <activeRecipes>
      <recipe>orcun.CommonStaticAnalysis</recipe>
    </activeRecipes>
  </configuration>
  <dependencies>
    <dependency>
      <groupId>org.openrewrite.recipe</groupId>
      <artifactId>rewrite-static-analysis</artifactId>
      <version>1.3.1</version>
    </dependency>
  </dependencies>
</plugin>








22 Ocak 2024 Pazartesi

Project Panama - Bridge The Gap Between Java And Native Code

Giriş
Açıklaması şöyle
Project Panama represents a significant advancement in the Java ecosystem, primarily focusing on enhancing Java’s interaction with foreign APIs, particularly those written in languages like C and C++. Traditionally, Java used the Java Native Interface (JNI) to invoke foreign functions, but JNI had several limitations. Project Panama addresses these by removing the need to write native code wrappers in Java, replacing the ByteBuffer API with a more advanced Memory API, and introducing a secure, memory-efficient method to invoke native code from Java. The project comprises several key components, including the Foreign-Function and Memory API, the Vector API, and the JExtract tool​​.

19 Ocak 2024 Cuma

JEP-401 - Project Valhalla - Improve Java’s Memory Efficiency

Giriş
Java'nın kullandığı Memory Model özellikle Integer[] gibi yapılarda işlemcinin israf edilmesine sebep oluyor. Bunu gösteren bir şekil burada

Sebebi ise şöyle
Accessing the value of an Integer (non-primitive) includes an extra memory access
Çünkü her bir Integer için kullanılan Metadata nesnesi bellekte rastgele bir yerde duruyor
Bu da günümüzdeki modern işlemcilerde CPU cache israfına sebep oluyor

Project Valhalla
İlk fikir 2014 yılında ortaya atıldı. Açıklaması şöyle
... give the user the ability to flatten his objects and enjoy the performance of primitives in exchange for some limitations ...
Kod olarak şöyle
// Before
public class Point {
  private final int x;
  private final int y;
}

// After
public primitive class Point {
  private final int x;
  private final int y;
}



7 Ocak 2024 Pazar

GSON Kullanımı

Maven
Şu satırı dahil ederiz
<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <version>2.8.9</version>
</dependency>
Gson Sınıfı
Gson Sınıfı toJson() ile nesneyi JSON String'e çevirir. fromJson() ile JSON String'den nesneye çevirir

@SerializedName Anotasyonu
@SerializedName Anotasyonu yazısına taşıdım

@Expose Anotasyonu
@Expose Anotasyonu yazısına taşıdım

@Since Anotasyonu
@Since Anotasyonu yazısına taşıdım

Gson @Since Anotasyonu - Specify Version Information For Fields

Örnek
Şöyle yaparız
import com.google.gson.annotations.Since;
import com.google.gson.annotations.Until;

public class Product {
    @Since(1.0)
    private String name;
    @Until(2.0)
    private double price;

    // getters and setters
}


2 Ocak 2024 Salı

Hikari API HikariDataSource Sınıfı

Giriş
Şu satırı dahil ederiz
import com.zaxxer.hikari.HikariDataSource;
constructor
Örnek
Hikari sayfasındaki örnek şöyle
HikariConfig config = ...
HikariDataSource ds = new HikariDataSource(config);
isClosed metodu
Sınıf şöyle
public class HikariDataSource extends HikariConfig implements DataSource, Closeable {
  ...
  private final AtomicBoolean isShutdown = new AtomicBoolean();
  ...
}
Metodun içi şöyle
public boolean isClosed() {
  return isShutdown.get();
}