1 Temmuz 2015 Çarşamba

Spring AOP

Aspect ve Around Nedir?
Metoda girmeden önce ve girdikten sonra çağırılan kod parçasına around denilir.

Eğer Aspect kullanamıyorsak ve elle bir şey yazmak gerekiyorsa çözüm olarak ExecuteAround Idiom ile kullanılabilir.


AOP Kullanımı
Spring ile AOP kullanmak için iki yöntem var. Birincisi Spring'in kendi AOP paketleri, diğeri ise AspectJ derleyicisi. Spring'in kendi AOP paketlerini kullanınca - altta ya JDK Dynamic Proxy ya da CGLIB kullanıyor - şöyle bir dezavantaj var ki aslında sitede yazmasına rağmen pek dikkat çekmiyor.
"Due to the proxy-based nature of Spring's AOP framework, protected methods are by definition not intercepted, neither for JDK proxies (where this isn't applicable) nor for CGLIB proxies (where this is technically possible but not recommendable for AOP purposes). As a consequence, any given pointcut will be matched against public methods only!
If your interception needs include protected/private methods or even constructors, consider the use of Spring-driven native AspectJ weaving instead of Spring's proxy-based AOP framework. This constitutes a different mode of AOP usage with different characteristics, so be sure to make yourself familiar with weaving first before making a decision."
Yani buradan aldığım şekilde de görüldüğü gibi Spring AOP ile sadece public metotları kesme yöntemi bulunuyor.
İlk şekilde normal çağrı sırasını görebiliriz.
Daha sonra bu çağrıya bir aspect eklemek istersek proxy yöntemi kullanıldığı için sadece public metotları yakalayabiliyoruz.
Calling a Spring Bean's Method with Different Transaction Attributes? sorusuna verilen cevapta da Spring AOP ile sadece dışarıdan ilk çağırılan metod için transaction açılacağı, metodun içinde çağırılan diğer public metodlar içinse transaction açılmadığı için hiç bir etkisinin olmayacağı yazılı.


JDK Dynamic Proxy
Spring mümkün olduğunca JDK Dynamic Proxy yeteneğini kullanmaya çalışıyor. Bu yeteneği kullanmanın ön koşulu proxy üretilecek sınıfın bir arayüzden türemesiBuradaki soruda arayüzde bulunmaya metodların problem çıkarabileceği anlatılmış. Dolayısıyla JDK Dynamic Proxy yeteneğinin @Transactional ile birlikte kullanılabilmesi için burada görülebildiği @Transactional ile işaretli her metodun arayüzde de bulunması gerekiyor.

Proxy sınıfını kullanmak isteseydik şöyle yapardık. Önce bir arayüz tanımlardık.
public interface Foo {
    public boolean getIsEnabled();
    public void setIsEnabled(boolean enable);
    public void bar();
    public void baz();
    public void bat();

    /*
    Convenience method that can be added in Java 8
    to make the calling code a bit more intuitive.

    public static Foo newFoo() {
        FooBuilder fooBuilder = new FooBuilder();
        return fooBuilder.buildFoo();
    }
    */
}
Daha sonra bir builder sınıfı kodlamamız gerekir. Builder içinde hem arayüzü gerçekleştirren Impl sınıfı hem de bir InvocationHandler kullanmamız gerekir.
public class FooBuilder {
    public Foo buildFoo() {
        return (Foo)Proxy.newProxyInstance(
            this.getClass().getClassLoader(),
            new Class[] { Foo.class },
            new FooInvocationHandler(new FooImpl()));
    } 
}
InvocationHandler metodlar çağrılmadan önce çalıştırılan bir metoda sahip
class FooInvocationHandler implements InvocationHandler {
  private FooImpl foo;

  public FooInvocationHandler(FooImpl foo) {
    this.foo = foo;
  }

  @Override
  public Object invoke(Object proxy,Method method,Object[] args)throws Throwable{
    if (method.getDeclaringClass() == Foo.class &&
       !method.getName().equals("getIsEnabled") &&
       !method.getName().equals("setIsEnabled")) {

       if (!this.foo.getIsEnabled()) {
         return null;
       }
    }

    return method.invoke(this.foo, args);
  }
}










29 Haziran 2015 Pazartesi

Sistem Saatini Değiştirmek

Giriş
Normalde sistem saati ile oynamamak gerekir. NTP kurarak bu iş halledilir. Ancak birçok işletim sistemi sistem saatini değiştirmek için API de sunar. Sistem saatini almakla ilgili Epoch ve API başlıklı yazıya da göz atabilirsiniz.

Java
Java'da sistem saatini değiştirmek için bir API yok. Ancak harici bir uygulama kullanılarak bu iş yapılabilir. Windows'ta şöyle yaparız.
Runtime.getRuntime().exec("cmd /C date " + strDateToSet); // dd-MM-yy
Runtime.getRuntime().exec("cmd /C time " + strTimeToSet); // hh:mm:ss
Linux'ta ise şöyle yaparız.
Runtime.getRuntime().exec("date -s " + strDateTimeToSet); // MMddhhmm[[yy]yy]
Windows
SetSystemTime
C# örneği
[DllImport("kernel32.dll", SetLastError = true)]
extern static uint SetSystemTime(ref SYSTEMTIME systime);

private struct SYSTEMTIME
{
  public ushort wYear;
  public ushort wMonth;
  public ushort wDayOfWeek;
  public ushort wDay;
  public ushort wHour;
  public ushort wMinute;
  public ushort wSecond;
  public ushort wMilliseconds;
}

SYSTEMTIME systime = new SYSTEMTIME();
//..Populate systime
SetSystemTime(ref systime);

25 Haziran 2015 Perşembe

JVM Havuzları

Not : JVM ile ilgili tanımlamaları burada gördüğüm sözlükten okumak mümkün.

Komut Satırından Java Kaynak Dosyaları Derlemek
src altındaki bazı kaynak dosyaları derlemek için

set sourcefiles = src\main.java src\another.java
javac -d bin -cp lib\myjar.jar;lib\myotherjar.jar -sourcepath src -verbose %sourcefiles%


Java ClassPath
JVM ile alakası yok ancak not almak istedim. Bir jar dosyasını çalıştırmak için iki yol var. İlkinde CLASSPATH ortam değişkeni ile yüklenecek jar dosyalarının bulunduğu dizin belirtilir. Örnek:

set CLASSPATH=D:\Mylib\
Daha sonra java MyApp şeklinde çalıştırılır. 

İkincisinde ise jar dosyaları -cp ile belirtilir. Örnek:


Linux'ta ; yerine : karakteri kullanılır.Örnek:

Daha sonra yine aynı şekilde java MyApp şeklinde çalıştırılır.

JVM açılış ayarları
JVM hiç parametre kullanmadan açılırsa, mevcut belleğin belli yüzdelerini kullanacağını farz ederek açılır. Aşağıda JVM'in oluşturduğu alanlar ve büyüklüklerini atama örnekleri var.
 
Young Generation Nedir?

Bir çok nesnenin çok kısa süreliğine kullanılıp tekrar yok olacağı farz ediliyor. Bu kısa ömürlü nesneler Young Generation denilen havuzda toplanırlar. Young Generation iki kısımdan oluşuyor. Eden ve Survivor.

Eden:
Burada anlatıldığına göre Eden ismi nesneler burada doğdukları için verilmiş. Eğer nesne hayatta kalırlarsa "Young Generation" içindeki diğer alanlara  gönderilirler.

 Survivor:
Survivor da kendi içinde to ve from isimli iki havuzdan oluşuyor.

 
Permenant Generation Nedir ?
Bu konuda bir sürü karmaşık yazı var. Benim anladığım işin özeti şöyle. Eğer bir yazılımda çok fazla yüklenecek class ya da string varsa bazen bu hata alınabiliyor. Tek yapılması gereken -XX:MaxPermSize=128M gibi bir parametre ile daha yüksek bir değer vermek.

-Xmx işe yaramaz ! Boşuna uğraşmayın...

Burada da classloader'ın nasıl çalıştığı anlatılıyor.

Aşağıda buradan aldığım bir şekil var ve durumu çok güzel anlatıyor.

Tüm Heap

Tüm Heap'in büyüklüğünü almak için aşağıdaki kod parçası çalıştırılabilir.

Runtime rt = Runtime.getRuntime();
long maxMb = rt.maxMemory()/(1024*1024);
Old Generation Nedir?

Uzun ömürlü nesneler Old Generation denilen havuzda toplanırlar.


Young + Old Generation Büyüklüğünü Ayarlamak

-Xms500m : Bu alanın başlangıç büyüklüğünü ayarlar.
why jvm consume less memory than -Xms speicified? sorusunda da gösterildiği gibi top komutuyla bakılınca VIRT sütunu altındaki değer -Xms ile atanan değerden daha büyük olmalı.

-Xmx1024m : Bu alanın azami büyüklüğünü ayarlar
Bu ayarlar ile java.lang.OutOfMemoryError: Java heap space diye başlayan exceptionlardan genellikle kurtulmak mümkün oluyor. Şöyle kullanırız
$ java -Xms1025k -Xmx1025k -XshowSettings:vm  MyApp

32 bit JVM'ler için bu alanın alacağı en büyük değer -Xmx1628m civarında. Yani 1.6 gigabyte.
Verilen değer uygulama içinde şöyle görülebilir.
Runtime.getRuntime().maxMemory()

Young + Old Generation Büyüklüğünü Yüzde Olarak Ayarlamak

JVM hafıza alanlarını işletim sisteminden bir kere alınca, normal şartlar altında kullanmasa bile işletim sistemine iade etmek zorunda değildir. Ancak

-XX:MinHeapFreeRatio (default is 40)   ve
-XX:MaxHeapFreeRatio (default is 70)

seçenekleri ise kullanılmayan alanın geri verilmesi sağlanabilir. Örneğin ilk açılışta çok bellek lazımdır ve üst sınır yüksek tutulmalıdır. Ancak daha sonra bu kadar bellek gerekmez ve "boş alan" miktarı artar. Bu durumda JVM kullanmadığı alanları işletim sistemine geri verirse, diğer uygulamalar daha rahat çalışırlar.

Garbage Collector
GC elle optimize edilen koda göre her zaman daha yavaştır. Ancak optimizasyon herkesin harcı olmadığı için GC her zaman daha yavaştır anlamına gelmez.

Çoğu GC gerçekleştirimleri tek thread ile çalışır.

Garbage Collection ve Strong Reference

Strong Reference bir nesneye Root Set tarafından direkt erişilebilmesi demek. Bu tür nesneler GC tarafından yok edilmezler. Aşağıdaki şekilde Root Set tarafından Strong Reference ile erişilebilen nesneleri görmek mümkün.

Bir diğer şekilde ise aynı durumu bu sefer GC tarafından yok edilecek nesneler ile birlikte görmek mümkün. Özellikle birbirine strong reference ile bağlı olan 3 nesnenin oluşturduğu adacığın Root Set'e bağlı olmadıkları için kırmızı ile işaretlendiğine dikkat etmek lazım.


Thread'ler bir şekilde çalıştıkları müddetçe, strong reference'a sahipler. Thread yarattıktan sonra, herhangi bir referans tutulmasa bile, thread nesnesi çalıştığı müddetçe garbage collection'a uğramaz.

Unmanaged Resource'lar
Disposable başlıklı yazıya bakabilirsiniz.

JVM Environment Variables
Windows altında heap boyunu ayarlamak için eğer Oracle JVM kullanılıyorsa _JAVA_OPTIONS değişkeni atanabilir.
Headless Mode
Bu modda çalıştırılan java uygulamasına display ve keyboard verilmez. Örnek:


23 Haziran 2015 Salı

String Algoritmaları - Harf Çevrimi

TitleCase
Her kelimenin ilk harfini büyük harfe çevirir.

C#
Şöyle yaparız
string title = "war and peace";
TextInfo textInfo = new CultureInfo("en-US", false).TextInfo;
title = textInfo.ToTitleCase(title); //War And Peace
Eğer kendimiz yazmak isteseydik şöyle yapardık.
IEnumerable<char> CharsToTitleCase(string s)
{
    bool newWord = true;
    foreach(char c in s)
    {
        if(newWord) { yield return Char.ToUpper(c); newWord = false; }
        else yield return Char.ToLower(c);
        if(c==' ') newWord = true;
    }
}
Bu kodu şöyle kullanırız.
var asTitleCase = new string( CharsToTitleCase(myText).ToArray() );




21 Haziran 2015 Pazar

Concurrent Collections

Not 1:  Java'da Concurrent Kuyruk konusu geniş olduğu için ayrı bir yazı olarak buraya taşıdım.
Not 2: C#'ta Concurrent Kuyruk konusu geniş olduğu için ayrı bir yazı olarak buraya taşıdım.
Not 3: Actor Model'de shared state olmaz.

Kuyruk Teorisi
Kuyruk teorisi veri yapısı ile ilgili değil. Ancak dolaylı olarak kuyruğun ne kadar büyük olması gerektiği ve bekleme süresini matematiksel olarak gösterdiği için bilinmesi faydalı. M/M/1 kuyruğu bu teoride kullanılan basit bir kuyruk.

Amdalh Kanunu
Bu kanunda concurrent programlama modeline geçilse bile hızın paralelleştirilemeyen kod parçasına bağımlı olduğu belirtilmiş.Örneğin sadece %50'si paralelleştirilebilen bir kod parçasına 16 işlemci ekleyerek 2 kat hızlanma elde edilir. Bundan sonra eklenen işlemci sayısının bir etkisi olmaz.

Concurrent Collections
Aşağıda çeşitli dillerde gördüğüm concurrent veri yapıları ile ilgili aldığım notlar var. Öncelikle ACE, Java ve C# arasındaki temel felsefe farkına dikkat etmek lazım.

ACE kütüphanesi, strategy örüntüsünü izleyerek veri yapısına dışarıdan kilitleme mekanizmasının geçilmesi felsefesini benimsemiş. Böylece aynı veri yapısı, kullanıcının isteğine göre thread-safe olarak veya olmayarak kullanılabiliyor.

Java ve C# ise veri yapılarının thread-safe olan ve olmayan 2 farklı sınıfını sunuyor.

ACE ACE_Map_Manager
Örneği buradan aldım.

//Eğer istenirse
//ACE_Null_Mutex
//ACE_Thread_Mutex
//ACE_Recursive_Thread_Mutex
//ACE_RW_Mutex kullanılabilir
typedef ACE_Map_Manager<unsigned long, std::string, ACE_Thread_Mutex> StringMap; 
StringMap m_MapInstance;

typedef StringMap::lock_type ACE_MAP_LOCK_TYPE;
//Create a guard
ACE_Guard<ACE_MAP_LOCK_TYPE> l(m_MapInstance.mutex());
for(StringMap::iterator it = m_MapInstance.begin(), end = m_MapInstance.end(); it!=end; ++it)
{
    const std::string & strContent = (*it).int_id_;
    const unsigned long & ulID = (*it).ext_id_;
    //do something with the element here
}
C# Partitioner
Range Partitioning, Chunk Partitioning algoritmaları var.

EnumerablePartitionerOptions sınıfı

NoBuffering seçeneği
Eğer listedeki elemanları teker teker thread'lere dağıtmak istersek aşağıdaki gibi yapabiliriz.
List<string> _files = new List<string>();
Parallel.ForEach(Partitioner.Create(_files, EnumerablePartitionerOptions.NoBuffering),
                new ParallelOptions
                {
                    MaxDegreeOfParallelism = 5 //limit number of parallel threads
                },
                (file, loopstate, index) =>
                {
                    if (token.IsCancellationRequested)
                        return;
                    //do work...
                });


C# ConcurrentBag
Bu sınıf bag olduğu için sırasız yani unordered bir veri yapısı. Object Pool gibi sıranın önemli olmadığı veri yapılarında kullanmak için ideal. Sırasız çalıştığını aşağıdaki şekilde görebiliriz. Bu sınıf sanırım Java'daki ConcurrentHashMultiSet'e denk geliyor.
image

Add() ve TryTake() bu sınıfın en önemli metodları.

Örnek:
var stringResult = new ConcurrentBag<string>();
stringResult.Add ("line");
string item;
stringResult.TryTake (out item);//Bag'den bir eleman çek
C# ConcurrentDictionary
ConcurrentDictionary yazısına taşıdım.

Java ConcurrentHashMap
ConcurrentHashMap yazısına taşıdım.

Java ConcurrentSkipList
ConcurrentSkipListSet yazısına taşıdım.

Java ConcurrentSkipListMap
ConcurrentSkipListMap yazısına taşıdım


12 Haziran 2015 Cuma

Süre Temsili

Giriş
İki Tarih Arasındaki Fark yazısı verilen iki zaman aralığının kaç yıl, ay, hafta, gün, dakika vs. gibi birimler olarak ölçülebileceğini gösteriyor. Ölçümde kullanılan birimler kavramsal olarak "süre" kelimesiyle anlatılıyor.

Dolayısıyla programlama dilleri ve kütüphaneler süre kavramını ve çeşitli birimler cinsiden temsil edebilmek için çeşitli sınıflar sunuyorlar.

C#
TimeSpan sınıfı
TimeSpan yazısına taşıdım.

Boost
Saniye
Saniyeyi temsil etmek için boost::posixtime::seconds  sınıfı kullanılıyor. Örnek:
boost::posix_time::seconds(1)
Joda
Ay
Ayı temsil etmek için Months sınıfı kullanılıyor.

Gün
Günü temsil etmek için Days sınıfı kullanılıyor.
  
Saat
Saati temsil etmek için Hours sınıfı kullanılıyor. Hour sınıfı yaratmak için
Hours.hours(6);
yazılabilir veya Hours sınıfı içindeki static olarak önceden yaratılmış hazır Hours.ONE gibi nesneler kullanılabilir.


Dakika
Dakikayı temsil etmek için Minutes sınıfı kullanılıyor.

Milisaniye
Milisaniyeyi temsil etmek için Durationnıfı kullanılıyor. Sınıfın açıklamasında "specifying a length of time in milliseconds." deniliyor. Duration sınıfını yaratmak için bir çok seçenek mevcut. Örnek:
Duration.millis (1000);//1000 milisaniyelik süre
Duration.standardDays (1);//1 günün milisaniye olarak süresi
Duration.standardHours (1);//1 saatin milisaniye olarak süresi

Sürenin Bir Üst Süre Cinsi ile Yazılması
Saniyenin Dakika + Saniye Olarak Gösterilmesi
Basit bir örnek:
private String secondsToString(int pTime) {
    return String.format("%02d:%02d", ptime / 60, pTime % 60);
}