Burada en az iki farklı olası soru var gibi görünüyor. Bunlardan biri genel olarak derleyicilerle ilgilidir, Java temelde türün bir örneği. Diğeri, kullandığı belirli bayt kodlarını Java'ya özgüdür.
Genel olarak derleyiciler
Öncelikle genel soruyu düşünelim: neden bir derleyici belirli bir işlemci üzerinde çalışmak için kaynak kodu derleme sürecinde neden bir ara temsil kullanıyor?
Karmaşıklık Azaltma
Bunun bir cevabı oldukça basittir: O (N * M) problemini O (N + M) problemine dönüştürür.
Eğer N kaynak dilleri ve M hedefleri verilirse ve her derleyiciden tamamen bağımsız olursak, o zaman bütün bu kaynak dilleri tüm bu hedeflere çevirmek için N * M derleyicilerine ihtiyacımız var (burada bir "hedef" bir gibi bir kombinasyondur) işlemci ve işletim sistemi).
Bununla birlikte, tüm bu derleyiciler ortak bir ara temsil üzerinde hemfikirse, o zaman kaynak dilleri ara gösterime çeviren N derleyici ön uçlarına ve ara gösterimi belirli bir hedef için uygun bir şeye çeviren M derleyici arka uçlarına sahip olabiliriz.
Problem Segmentasyonu
Daha da iyisi, sorunu iki veya daha fazla ayrıcalıklı alana ayırır. Dil tasarımını, ayrıştırmayı ve bunun gibi şeyleri bilen / önemseyen insanlar, derleyici ön uçlarına konsantre olabilirken, komut setleri, işlemci tasarımı ve bunun gibi şeyleri arka uçta yoğunlaştırabilen insanlar.
Örneğin, LLVM gibi bir şey verildiğinde, farklı diller için birçok ön uçumuz var. Ayrıca birçok farklı işlemci için arka uçlarımız var. Bir dil adamı dili için yeni bir ön uç yazabilir ve hızlıca birçok hedefi destekleyebilir. İşlemci bir adam, dil tasarımı, ayrıştırma vb. İle uğraşmadan hedefi için yeni bir arka uç yazabilir.
Derleyicileri ön uç ve arka uç olarak ayırmak, ikisi arasında iletişim kurmak için bir ara temsil ile Java ile orijinal değildir. Uzun zamandır oldukça yaygın bir pratikti (Java gelmeden önce de zaten).
Dağıtım Modelleri
Java'nın bu konuda yeni bir şey eklediği ölçüde, dağıtım modelindeydi. Özellikle, derleyiciler uzun süre dahili olarak ön uç ve arka uç parçalarına ayrılsa da, tipik olarak tek bir ürün olarak dağıtıldılar. Örneğin, bir Microsoft C derleyicisi satın aldıysanız, dahili olarak sırasıyla "ön uç ve arka uç" olan bir "C1" ve "C2" ye sahipti. adet (ikisi arasında işlemleri koordine bir "derleyici sürücüsü" ile). Derleyici iki parça halinde oluşturulmuş olsa da, derleyiciyi kullanan normal bir geliştiriciye, kaynak kodundan nesne koduna çevrilmiş, aralarında hiçbir şey görünmeyen tek bir şeydi.
Java, bunun yerine, Java Geliştirme Seti'nde ön ucu ve Java Sanal Makinesi'nde arka ucu dağıttı. Her Java kullanıcısının kullandığı sistemi hedeflemek için bir derleyici arka ucu vardı. Java geliştiricileri ara formatta kod dağıttı, bu yüzden bir kullanıcı yüklediğinde, JVM kendi makinelerinde çalıştırmak için ne gerekiyorsa yaptı.
emsal
Bu dağıtım modelinin de tamamen yeni olmadığını unutmayın. Örneğin, UCSD P-sistemi benzer şekilde çalıştı: derleyici ön uçları P-kodu üretti ve P-sisteminin her kopyası, söz konusu hedef 1'de P-kodunu yürütmek için gerekli olanı yapan sanal bir makine içeriyordu .
Java bayt kodu
Java bayt kodu P koduna oldukça benzer. Bu oldukça basit bir makine için temelde bir talimattır . Bu makinenin mevcut makinelerin bir soyutlaması olması amaçlanmıştır, bu nedenle hemen hemen her belirli hedefe hızlı bir şekilde çevirmek oldukça kolaydır. Çeviri kolaylığı erken dönemde önemliydi, çünkü asıl amaç, P-System'in yaptığı gibi bayt kodlarını yorumlamaktı (ve evet, tam olarak ilk uygulamaların işleyiş şekli buydu).
Güçlü
Java bayt kodu derleyici ön uç üretmek için kolaydır. (Örneğin) bir ifadeyi temsil eden oldukça tipik bir ağacınız varsa, ağacı geçmek ve her düğümde bulduklarınızdan doğrudan kod oluşturmak oldukça kolaydır.
Java bayt kodları oldukça kompakt - çoğu durumda, çoğu tipik işlemcilerin (ve özellikle de Java'yı tasarlarken Sun'ın sattığı SPARC gibi çoğu RISC işlemcileri için) kaynak kodlarından veya makine kodlarından çok daha küçüktür. Bu özellikle önemliydi, çünkü Java’nın büyük bir niyeti, çoğu kişinin bize telefon hatları üzerinden 28.8’de modemler aracılığıyla erişdiği bir zamanda, uygulamaları - web sayfalarına gömülü kodları - desteklemekti. Saniyedeki kilobit sayısı (tabii ki, daha eski ve daha yavaş modem kullanan birkaç kişi vardı).
Zayıf Yönler
Java bayt kodlarının en büyük zayıflığı, özellikle anlamlı olmadıklarıdır. Java'da bulunan kavramları oldukça iyi ifade edebilmelerine rağmen, Java'nın bir parçası olmayan kavramları ifade etmek için neredeyse çok iyi çalışmıyorlar. Benzer şekilde, çoğu makinede bayt kodlarını çalıştırmak kolay olmakla birlikte, herhangi bir makineden tam olarak yararlanabilecek şekilde daha zordur.
Örneğin, eğer gerçekten Java byte kodlarını optimize etmek isterseniz, temelde temsil etmek gibi, makine kodundan geriye çevirmek ve geri SSA talimatlarına (veya benzer bir şey) haline getirmek için bazı ters mühendislik yapmak oldukça rutin 2 . Daha sonra, optimizasyonunuzu yapmak için SSA talimatlarını değiştirirsiniz, ardından oradan gerçekten ilgilendiğiniz mimariyi hedefleyen bir şeye çevirirsiniz. Bununla birlikte, oldukça karmaşık olan bu süreçte bile, Java'ya yabancı olan bazı kavramların, bazı kaynak dillerden, çoğu tipik makinede en iyi şekilde çalışan (hatta yakın) makine koduna çevrilmesinin zor olduğunu ifade etmek yeterince zordur.
özet
Genel olarak ara temsilleri neden kullandığınızı soruyorsanız, iki ana faktör şunlardır:
- Bir O (N * M) problemini O (N + M) problemine azaltın ve
- Sorunu daha yönetilebilir parçalara ayırın.
Java bayt kodlarının özelliklerini ve neden bu belirli temsili başka bir seçtikleri yerine seçtiklerini soruyorsanız, o zaman cevabın büyük ölçüde orijinal niyetlerine ve webin sınırlamalarına geri döndüğünü söyleyebilirim. aşağıdaki önceliklere öncülük eder:
- Kompakt gösterim
- Çözülmesi ve yürütülmesi hızlı ve kolaydır.
- Yaygın olarak kullanılan makinelerde hızlı ve kolaydır.
Birçok dili temsil edebilmek veya çok çeşitli hedeflerde en iyi şekilde uygulama yapabilmek çok daha düşük önceliklerdir (eğer öncelikler olarak kabul edilmişlerse).
- Peki neden P-sistemi çoğunlukla unutulur? Çoğunlukla bir fiyatlandırma durumu. P-sistemi Apple II, Commodore SuperPets, vb. Cihazlarda oldukça nezih satıldı. IBM PC çıktığında, P sistemi desteklenen bir işletim sistemi idi, ancak MS-DOS daha ucuza mal oldu (çoğu insanın bakış açısından aslında bedavaya verildi) ve Microsoft ve IBM'in (diğerlerinin yanı sıra) yazdığı şeyden dolayı hızla daha fazla program hazırladı.
- Örneğin, Soot böyle işler.