Java 8 kodu Java 7 JVM üzerinde çalışacak şekilde derlenebilir mi?


163

Java 8, lambda ifadeleri gibi önemli yeni dil özelliklerini sunar.

Dildeki bu değişikliklere, derlenmiş bayt kodunda, bir retrotranslator kullanmadan Java 7 sanal makinesinde çalışmasını engelleyecek önemli değişiklikler eşlik ediyor mu?


Yanıtlar:


146

Hayır, kaynak kodunuzda 1.8 özellik kullanmak 1.8 VM'yi hedeflemenizi gerektirir. Yeni Java 8 sürümünü denedim ve derlemeyi denedim -target 1.7 -source 1.8ve derleyici reddediyor:

$ javac Test -source 1.8 -target 1.7
javac: source release 1.8 requires target release 1.8

4
Hayır, olacağını sanmıyorum. Java, masaüstü pazarında küçük bir paya sahiptir, ancak bu küçük payı oldukça sıkı bir tutuşta tutar. Ancak yeni sürümlerin ve özelliklerin benimsenmesini engelliyor. İnsanların yerel Java kurulumlarını yükseltmek zorunda kalmamak için, yazdığım kodda Java 8 özelliklerini kullanamayacağım.
JesperE

Neden? "Evet", Java 8'in Java 8 derleyicisine göre yanlış olan bir Java 7 VM'de çalışacak şekilde derlenebileceğini ima eder.
JesperE

5
Şimdi görüyorum: "Hayır" sorunuzun başlığını değil, sorunun başlığını cevaplıyor.
Abdull

58

Varsayılan yöntemler, Java 7'de bayt kodu ve JVM'de bu tür değişikliklerin yapılmasını imkansız kılar. Varsayılan yöntemleri arayan tarafında statik yöntemlerle taklit etmeye çalışmak aynı sonuçları üretmez, çünkü varsayılan yöntemler alt sınıflarda geçersiz kılınabilir. Retrolambda , varsayılan yöntemler backporting için sınırlı desteğe sahiptir, ancak yeni JVM özellikleri gerektirdiğinden asla tam olarak rapor edilemez.

Gerekli API sınıfları orada mevcut olsaydı, Lambdas Java 7'de olduğu gibi çalışabilirdi. İnfürodinamik talimat Java 7'de bulunur, ancak lambda sınıflarını derleme zamanında (böylece JDK 8'in erken yapısını bu şekilde yapar) oluşturacak şekilde uygulamak mümkün olurdu, bu durumda herhangi bir Java sürümü üzerinde çalışacaktır. (Oracle gelecekteki prova için lambdas için invokedynamic kullanmaya karar verdi; belki bir gün JVM birinci sınıf işlevlere sahip olacaktır, bu nedenle invokedynamic, her lambda için bir sınıf oluşturmak yerine bunları kullanmak için değiştirilebilir, böylece performansı iyileştirir.) Retrolambda'nın yaptığı tüm bu invokinamik talimatları işlediğini ve anonim sınıflarla değiştirdiğini; bir lamdba invokedynamic ilk kez çağrıldığında Java 8'in çalışma zamanında yaptığı ile aynı.

Ek Açıklamaları tekrarlamak sadece sözdizimsel şekerdir. Önceki sürümlerle bayt kod uyumludurlar. Java 7'de, kendinize tekrarlanan ek açıklamaları içeren bir konteyner ek açıklamasının uygulama ayrıntılarını gizleyen yardımcı yöntemleri (örn. GetAnnotationsByType ) uygulamanız gerekir.

AFAIK, Tür Ek Açıklamaları yalnızca derleme zamanında mevcuttur, bu nedenle bayt kodu değişiklikleri gerektirmemelidir, bu nedenle yalnızca Java 8 ile derlenmiş sınıfların bayt kodu sürüm numarasını değiştirmek, Java 7'de çalışabilmeleri için yeterli olmalıdır.

Yöntem parametre adları Java 7 ile bayt kodunda bulunur, bu da uyumludur. Yöntemin bayt kodunu okuyarak ve yöntemin hata ayıklama bilgilerindeki yerel değişken adlarına bakarak bunlara erişebilirsiniz. Örneğin Spring Framework, @PathVariable'ı uygulamak için tam olarak bunu yapar ; bu nedenle, çağırabileceğiniz bir kitaplık yöntemi vardır. Soyut arabirim yöntemlerinin bir yöntem gövdesi olmadığından, bu hata ayıklama bilgileri Java 7'deki arabirim yöntemleri ve AFAIK için de Java 8'de bulunmaz.

Diğer yeni özellikler çoğunlukla yeni API'ler, HotSpot'taki iyileştirmeler ve araçlardır. Yeni API'ler bazıları 3. parti kütüphaneleri (örn olarak mevcuttur ThreeTen-backport ve streamsupport ).

Summa summarum, varsayılan yöntemler yeni JVM özellikleri gerektirir, ancak diğer dil özellikleri gerektirmez. Bunları kullanmak istiyorsanız, kodu Java 8'de derlemeniz ve ardından Retrolambda ile bayt kodunu Java 5/6/7 biçimine dönüştürmeniz gerekir. En azından bayt kodu sürümünün değiştirilmesi gerekir ve javac izin vermez, -source 1.8 -target 1.7bu nedenle bir retrotranslator gereklidir.


3
Aslında tür ek açıklamaları çalışma zamanında görülebilir. stackoverflow.com/questions/22374612/…
Antimon

33

Bildiğim kadarıyla JDK 8'deki bu değişikliklerin hiçbiri yeni bayt kodlarının eklenmesini gerektirmedi. Lambda enstrümantasyonunun bir kısmı invokeDynamic(zaten JDK 7'de mevcut olan) kullanılarak yapılmaktadır. Bu nedenle, JVM komut kümesi açısından hiçbir şey kod tabanını uyumsuz yapmamalıdır. Yine de, JDK 8 kodunu derlemek / önceki JDK'lar altında çalıştırmak zorlaştıracak API ile ilişkili ve derleyici geliştirmeleri bir sürü vardır (ancak bunu denemedim).

Belki de aşağıdaki referans materyalleri, lambda ile ilgili değişikliklerin nasıl gerçekleştirildiğinin anlaşılmasını bir şekilde zenginleştirmeye yardımcı olabilir.

Bunlar, olayların başlık altında nasıl kullanıldığını ayrıntılı olarak açıklar. Belki sorularınızın cevabını orada bulabilirsiniz.


7
Yeni bayt kodları değil, yeni yapılar. Doğrulayıcı kusacak.
Jonathan S. Fisher

12
Buna iyi bir örnek Arayüzlerdir. Artık yöntemler içerebilirler. Java7 doğrulayıcısı bununla başa çıkmak için donanımlı değildir. Tüm eski bayt kodları kullanılır, ancak yeni bir şekilde.
Jonathan S. Fisher

1
Ben pek çok dil özellikleri ile scala derleyici nasıl jdk5 bile hedef jvm sürümü elde edebilirsiniz merak ediyorum.
Marinos

1
@MarinosAn Tam olarak ne demek istiyorsun? Somut yöntemler içeren özelliklere sahip MI, class C extends A with Bnormal arayüzler Ave Bve eşlik sınıfları ile uygulanır A$classve B$class. class C, yöntemleri statik tamamlayıcı sınıflara iletir. Benlik türleri hiç uygulanmaz, lambdalar derleme zamanında soyut iç sınıflara aktarılır, yani bir new D with A with Bifade. Desen eşleştirme, if-else yapılarının bir demetidir. Yerel olmayan iadeler? lambda denemeyi yakalama mekanizması. Geriye kalan bir şey var mı? (İlginçtir, benim scalac'ım 1.6 varsayılan olduğunu söylüyor)
Adowrath

1
Tabii ki, kendi kendine türler vb. Özel sınıf öznitelikleri ve ek açıklamalarıyla kodlanır, böylece scalac zaten derlenmiş sınıfları kullanırken kuralları kullanabilir ve uygulayabilir.
Adowrath


-5

Yapabilirsin -source 1.7 -target 1.7o zaman derler. Ancak lambdas gibi java 8'e özgü özellikleriniz varsa derlenmeyecek


Soru, yeni dil özelliklerinin kullanımını açıkça ortaya koyuyor, bu yüzden -source 1.7uçmuyor.
toolforger
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.