15 Nisan 2015 Çarşamba

JVM ve Java'nın platform bağımsızlığı üzerine.

JVM nedir?

JVM yani Java Virtual Machine, Java dilinde yazılan programların her platformda (farklı işlemci ya da işletim sistemlerinde) çalışabilmesi için geliştirilmiş olan, fiziksel bir bilgisayar gibi program çalıştırabilen bir sanal makinedir.

Örneğin windows pc'de derlenen bir .class dosyası, bir linux makinede hiçbir işlem gerektirmeden çalışır.

Derlenen kodun boyutu kaynak koddan neredeyse farksız olduğundan, derlenen java kodunun network üzerinden transfer edilmesi  ya da çalıştırılması kolaydır.

java laucher tool ile çalıştırıldığında Java uygulamasını okuyup Java API ile birlikte çalıştırır.

JVM kaç tanedir, kime aittir?

Bir çok JVM vardır. Genel olarak kullanılan Oracle JVM'dir.
Örneğin Andoid işletim sistemini kullanan cihazlarda Dalvik VM bulunur. O da bir JVM'dir.

javac nedir?

javac yani Java compiler, .java uzantılı metin dosyaları şeklinde yazılan java kaynak kodlarını alır,  .class dosyaları içerisine bytecode'lar şeklinde platform mimarisinden bağımsız (arhitecture neutral) kodlar halinde derler.

c/c++ gibi dillerde compiler kaynak kodunu direkt olarak CPU instructionlarına çevirir.
Fakat java compiler platform-bağımsız olduğundan JVM'in anladığı makine dili olan bytecode'lara çevirir.

javac MyApplication.java şeklinde komut verdiğimizde, java compiler java kodlarını derleyerek MyApplication.class şeklinde dosyalar içindeki bytecode'lar oluşturur.

bytecode nedir?

Bytecode'lar JVM'in anladığı makine dilidir. Bir nevi java kodu ile makine kodu arasında bir ara-dildir.

Her platform için özel olarak yazılmış JVM'ler bu bytecode'ları alarak interpreter aracılığıyla alttaki platforma uygun hale çevirerek çalıştırır.
(Java'nın interpreted yani çevirilen bir dil olması bu yüzdendir.)

Böylece kodun belirli platformlara göre yazılıp derlenmesine gerek kalmaz.
Yazılımcı java programının hangi platformda çalışacağını düşünmeden kendi işine odaklanabilir.

Örneğin javadaki tiplerin bytecode'daki karşılıkları aşağıdaki gibidir:

Java BytecodeTypeDescription
Bbytesigned byte
CcharUnicode character
Ddoubledouble-precision floating-point value
Ffloatsingle-precision floating-point value
Iintinteger
Jlonglong integer
L<classname>referencean instance of class <classname>
Sshortsigned short
Zbooleantrue or false
[referenceone array dimension
---

Örneğin bazı java kodlarının bytecode'daki ifade edilişi aşağıdaki gibidir:

Java CodeJava Bytecode Expression
double d[][][];[[[D
Object mymethod(int I, double d, Thread t)(IDLjava/lang/Thread;)Ljava/lang/Object;
--

Java bytecode'un instruction seti yani komut yapısı bir opCode ve Operand'dan oluşur.
Örneğin invokevirtual komutunun 2 byte'lık bir Operand alması gerekir.

javap nedir?

Binary bir dosya olduğundan insanlar tarafından okunup anlaşılamaz.
JVM ile gelen javap adlı java dissassembler aracı, bytecode ları komutlara çevirir.
Bu komutlara java assembly denir.
javap -c opsiyonu ile çalıştırıldığında class dosyasınının java assembly ye çevrilmiş halini görebiliriz.

Java assembly örneği:

public void add(java.lang.String);
  Code:
   0:   aload_0
   1:   getfield        #15//Field admin:Lcom/nhn/user/UserAdmin;
   4:   aload_1
   5:   invokevirtual   #23//Method com/nhn/user/UserAdmin.addUser:(Ljava/lang/String;)Lcom/nhn/user/User;
   8:   pop
   9:   return


Aynı bytecode'un hex editördeki görüntüsü:

2a b4 00 0f 2b b6 00 17 57 b1
(Yeşil renkli byte'lar opCode'ları, diğerleri Operand'ları gösteriyor.)

İkinci komut olan "1: getfield #15;" satırında, 15. index pozisyonundaki field ın alınacağını gösteriyor.
Yandaki açıklamada Field kelimesi ile neyin parametre olarak alındığını gösteriyor. 
Başındaki L harfi class instance demektir.
Yani bir UserAdmin class instance'ı parametre olarak alınmış.

Dördüncü komut olan "5: invokevirtual #23;" satırında 23. index pozisyonundaki metodun çalışacağını anlıyoruz.
Yandaki açıklamada Method kelimesi ile UserAdmin sınıfının addUser() metodunun çağırıldığını gösteriyor.
Parantez içindeki L ve String den bir String parametre alındığını anlıyoruz.
Parantezden sonraki L ve User'dan da metodun bir User instance'ı return ettiğini anlıyoruz.
Burada Lcom/... yerine sadece V yazarsa, metodun return tipi void yani hiçbir şey return etmiyor demektir.

opcode nedir?

http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-7.html
http://en.wikipedia.org/wiki/Java_bytecode_instruction_listings

Java bytecode'da komutları tanımlayan operasyon kodlarıdır.
2 byte boyutunda olduklarından en fazla 256 tane olabilir.
Bazı opCode byte'ları:
aload_0 = 0x2a
getfield = 0xb4
invokevirtual = 0xb6
java assembly'de her opCode'un başında bir sayı bulunur. Bu sayı byte sıra numarasıdır.
İlk baştaki opCode 0 sıra numarasını alır, bundan sonraki kodlar da dosyada kaçıncı byte ise o sıra numarasını alır.

Java bytecode'da metodları çağırmakta kullanılan 4 tane operasyon kodu vardır:

1. invokevirtual
    instance metodlarını çağırır. En çok kullanılan kod budur.
    opCode no.182,    bytecode 0xb6 

2. invokespecial
    initalizer, private ya da superclass metodlarını çağırır.
    opCode no.183,    bytecode 0xb7

3. invokestatic
    statik metodları çağırır.
    opCode no.184,    bytecode 0xb8 

4. invokeinterface
    bir interface metodunu çağırır.
    opCode no.185,    bytecode 0xb9

5. invokedynamic
    java SE7 ile kullanılmaya başlandı. (JSR-292)
    Kullanıcı tarafından nasıl uygulanacağı belirlenebilen bir bytecode'dur.
    Tip bilgisi verilmeden metod çağırılabilmesini mümkün kılar.
    opCode no.186,    bytecode 0xba
    http://blog.headius.com/2008/09/first-taste-of-invokedynamic.html
    http://www.javaworld.com/article/2860079/scripting-jvm-languages/invokedynamic-101.html

JVM'in özellikleri nelerdir?

1. Stack temellidir: Intel x86 ve ARM mimarileri register temelli çalışır. JVM ise stack üzerinden çalışır.
2. Sembolik referanslar: Primitif tipler hariç bütün tipler (yani class ve interface tipleri) sembolik referanslarla refere edilir. Explicit şekilde bellek adresini işaret etmez.
3. Garbage collection: Bir class instance ı kullanıcı koduyla yaratılır fakat kullanılması bittiğinde garbage collection ile otomatik olarak yokedilir.
4. Primitif veri tiplerini net bir şekilde belirterek platform bağımsızlığını garanti etmesi:
c/c++ gibi dillerde platforma göre int tipinin boyutu değişebilir. JVM primitif tipleri net bir şekilde tanımladığı için üzerinde çalıştığı platformdan bağımsız kalabilmeyi garantilemiştir.
5. Network byte order: Java class dosyaları network byte order kullanır. Intel x86 mimarisinde little endian, RISC serisi mimarisinde big endian sırası kullanılır. JVM platform bağımsız olmak için daima network transferinde kullanılan network byte order yani big endian sıralamasını kullanır.

JRE nedir?
JRE yani Java Runtime Environment, içerisinde Java API ve JVM bulundurur.
Java API de temel java kütüphaneleri bulunur.

JDK nedir?
JDK yani Java Development Kit,

java launcher tool nedir?
java komutuyla uygulamayı çalıştırmamızı sağlayan yükleyicidir.
java MyApplication şeklinde uygulamayı çalıştırma komutu verdiğimizde java launcher tool yeni bir JVM instance'ı yaratarak içerisinde uygulamayı çalıştırır.

WORA nedir?
WORA yani "Write once, run anywhere" kavramı java kodlarının bir kere yazılıp her platformda aynı kodun çalıştırılabilmesini ifade eder.
Java WORA kavramını gerçekleştirebilmek için platform-bağımsız olan bytecode'ları kullanır.

JVM'in sınırlamaları nelerdir?

ClassFile yapısındaki sınırlamaların bütünü JVM'in sınırlamalarını oluşturur.

Bir java metodunun boyutu 65535 karakteri geçemez.
Bir class yada interface'deki field sayısı, metod sayısı, superinterface sayısı, 65535i geçemez.
...
http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.11
  • The per-class or per-interface constant pool is limited to 65535 entries by the 16-bit constant_pool_count field of the ClassFile structure (§4.1). This acts as an internal limit on the total complexity of a single class or interface.
  • The number of fields that may be declared by a class or interface is limited to 65535 by the size of the fields_count item of the ClassFile structure (§4.1).
    Note that the value of the fields_count item of the ClassFile structure does not include fields that are inherited from superclasses or superinterfaces.
  • The number of methods that may be declared by a class or interface is limited to 65535 by the size of the methods_count item of the ClassFile structure (§4.1).
    Note that the value of the methods_count item of the ClassFile structure does not include methods that are inherited from superclasses or superinterfaces.
  • The number of direct superinterfaces of a class or interface is limited to 65535 by the size of the interfaces_count item of the ClassFile structure (§4.1).
  • The greatest number of local variables in the local variables array of a frame created upon invocation of a method (§2.6) is limited to 65535 by the size of the max_locals item of the Code attribute (§4.7.3) giving the code of the method, and by the 16-bit local variable indexing of the Java Virtual Machine instruction set.
    Note that values of type long and double are each considered to reserve two local variables and contribute two units toward the max_locals value, so use of local variables of those types further reduces this limit.
  • The size of an operand stack in a frame (§2.6) is limited to 65535 values by the max_stack field of the Code attribute (§4.7.3).
    Note that values of type long and double are each considered to contribute two units toward the max_stack value, so use of values of these types on the operand stack further reduces this limit.
  • The number of method parameters is limited to 255 by the definition of a method descriptor (§4.3.3), where the limit includes one unit for this in the case of instance or interface method invocations.
    Note that a method descriptor is defined in terms of a notion of method parameter length in which a parameter of type long or double contributes two units to the length, so parameters of these types further reduce the limit.
  • The length of field and method names, field and method descriptors, and other constant string values (including those referenced by ConstantValue (§4.7.2) attributes) is limited to 65535 characters by the 16-bit unsigned length item of the CONSTANT_Utf8_info structure (§4.4.7).
    Note that the limit is on the number of bytes in the encoding and not on the number of encoded characters. UTF-8 encodes some characters using two or three bytes. Thus, strings incorporating multibyte characters are further constrained.
  • The number of dimensions in an array is limited to 255 by the size of the dimensions opcode of the multianewarray instruction and by the constraints imposed on the multianewarrayanewarray, andnewarray instructions (§4.9.1§4.9.2).

JVM hataları nelerdir?

http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-6.html#jvms-6.3

VirtualMethodError sınıfının bütün alt sınıfları birer JVM hatasıdır.

1. InternalError
An internal error has occurred in the Java Virtual Machine implementation because of a fault in the software implementing the virtual machine, a fault in the underlying host system software, or a fault in the hardware. This error is delivered asynchronously (§2.10) when it is detected and may occur at any point in a program.

2. OutOfMemoryError
The Java Virtual Machine implementation has run out of either virtual or physical memory, and the automatic storage manager was unable to reclaim enough memory to satisfy an object creation request.

3. StackOverflowError
The Java Virtual Machine implementation has run out of stack space for a thread, typically because the thread is doing an unbounded number of recursive invocations as a result of a fault in the executing program.

4. UnknownError
An exception or error has occurred, but the Java Virtual Machine implementation is unable to report the actual exception or error.

...

JVM nelerden oluşur?

compiler: Standard Java compiler. When the CREATE JAVA SOURCE statement is run, it translates Java source files into architecture-neutral, one-byte instructions known as bytecodes. 

interpreter: To run Java programs, Oracle JVM includes a standard Java2 bytecode interpreter. The interpreter and the associated Java run-time system run standard Java class files. The run-time system supports native methods and call-in and call-out from the host environment. 

library manager: Loads java source, class and resource files into the database 

class loader: During runtime finds the java class, and loads and initializes java classes for Oracle JVM
verifier: works with oracle and java security to validate java classes 

server-side internal jdbc driver: java driver in the oracle database supporting java database calls 

server-side SQLJ translator: translates SQLJ code into JDBC code 

system classes: A set of classes that constitute a significant portion of the implementation of Java in Oracle Database environment, defined in the SYS schema and exported for all users by public synonym.
...

1 yorum: