Java'da satır içi işlevler var mı?


112

Java'da satır içi işlevler kavramı var mı, yoksa yerini başka bir şey mi alıyor? Varsa nasıl kullanılır? Ben duydum public, staticve finalyöntemler satır içi fonksiyonlardır. Kendi satır içi işlevimizi oluşturabilir miyiz?


4
Sadece açıklığa kavuşturmak için, en.wikipedia.org/wiki/Inline_function demek istiyorsunuz , en.wikipedia.org/wiki/Anonymous_function değil , değil mi?
JW.

3
Küçük bir yorum olarak, erken optimizasyon tüm kötülüklerin köküdür. Kamusal, statik ve nihai niteliğini tam olarak anlamadan, satır içi yapmanın sahip olabileceği etkiyi gerçekten anlayamazsınız - ve bu, kullandığınız JVM'ye bağlıdır. İlk önce neden bir şeyi satır içi yapmanız gerektiğini yanıtladığınızdan emin olun: Başka bir yerde yapabileceğiniz daha yüksek YG optimizasyonları olduğu neredeyse kesindir.
Nathaniel Ford

Yanıtlar:


123

Java'da optimizasyonlar genellikle JVM seviyesinde yapılır. Çalışma zamanında JVM, hangi yöntemlerin satır içi yapılacağını belirlemek için bazı "karmaşık" analizler gerçekleştirir. Satır içi olarak agresif olabilir ve Hotspot JVM aslında nihai olmayan yöntemleri satır içi yapabilir.

Java derleyicileri neredeyse hiçbir zaman herhangi bir yöntem çağrısını satır içi olarak gerçekleştirmez (JVM bunların hepsini çalışma zamanında yapar). Zaman sabitlerini satır içi derlerler (örneğin, son statik ilkel değerler). Ama yöntemler değil.

Daha fazla kaynak için:

  1. Makale: Java HotSpot Performans Motoru: Yöntem Satır İçi Örnek

  2. Wiki: OpenJDK'da satır içi , tam olarak doldurulmamış, ancak yararlı tartışmalara bağlantılar içerir.


15

Hayır, javada satır içi işlev yoktur . Evet, genel bir sınıfa yerleştirildiğinde kodun herhangi bir yerinde genel bir statik yöntem kullanabilirsiniz. Java derleyicisi, statik veya son bir yöntem üzerinde satır içi genişletme yapabilir , ancak bu garanti edilmez.

Tipik olarak bu tür kod optimizasyonları, çok sık kullanılan kod segmentleri için JVM / JIT / HotSpot ile birlikte derleyici tarafından yapılır. Ayrıca, parametrelerin kayıt bildirimi gibi diğer optimizasyon kavramları java'da bilinmemektedir.

Optimizasyonlar java'da bildirimle zorlanamaz, ancak derleyici ve JIT tarafından yapılır. Diğer birçok dilde, bu bildirimler genellikle yalnızca derleyici ipuçlarıdır (işlemcinin sahip olduğundan daha fazla yazmaç parametresi bildirebilirsiniz, geri kalanı yok sayılır).

Java yöntemlerinin statik, son veya özel olarak bildirilmesi de derleyici için ipuçlarıdır. Kullanmalısın, ama garanti yok. Java performansı dinamiktir, statik değil. Bir sisteme ilk çağrı, sınıf yüklemesi nedeniyle her zaman yavaştır. Sonraki çağrılar daha hızlıdır, ancak belleğe ve çalışma süresine bağlı olarak en yaygın çağrılar çalışan sistem içinde optimize edilir, bu nedenle bir sunucu çalışma süresi sırasında daha hızlı hale gelebilir!


3
finalJIT satır içi üzerinde hiçbir etki yapmayın
Steve Kuo

1
+1, Ancak bir yöntemin derlenmiş sürümünün satır içi olup olmadığını nasıl test edebiliriz ?
Pacerier

@Pacerier Ama neden bir şeyin satır içi olup olmadığını test etmeliyiz?
Arne Burmeister

14

Java, bir yöntemin satır içine alınması gerektiğini manuel olarak önermenin bir yolunu sağlamaz. @Notnoop'un yorumlarda dediği gibi, satır içi genellikle yürütme sırasında JVM tarafından yapılır.


3
Çoğu java derleyicisi asla satır içi yöntem çağrıları yapmaz. Çoğunlukla JVM bunu yapar.
notnoop

Bunu açıkladığınız için teşekkürler. Tam olarak hangi aşamada gerçekleştiğinden emin değildim. Yazımı bunu yansıtacak şekilde düzenleyeceğim.
Thomas Owens

@ThomasOwens öyle, ama halka açık değiljdk.internal.vm.annotation.ForceInline
Eugene

4

Yukarıda söylediğiniz doğru. Bazen son yöntemler satır içi olarak oluşturulur, ancak java'da açıkça bir satır içi işlev oluşturmanın başka bir yolu yoktur.


5
Nihai yöntemlerin satır içi olması garanti edilmez.
Thomas Owens

4
HotSpot'ta ekleme final, yöntemin satır içi olup olmadığı konusunda herhangi bir fark yaratmaz.
Tom Hawtin -

4
@Thomas - bu yüzden "Bazen son yöntemler ..."
dedim

@ TomHawtin-tackline Bunun için yetkili bir kaynağınız var mı? Bildiğim kadarıyla, son yöntemler bir tür koruması kullanmadan satır içi olarak yazılabilir, bu da değiştiricinin yöntemi satır içi yapmayı değiştirici olmadan olduğundan daha verimli hale getirdiği anlamına gelir. Jikes RVM'nin satır içi yapıp yapmamaya karar verirken bunu dikkate aldığını biliyorum. HotSpot'un benzer bir şey yapmadığından emin misiniz?
Jannik Jochem

2

Gerçek hayat örneği:

public class Control {
    public static final long EXPIRED_ON = 1386082988202l;
    public static final boolean isExpired() {
        return (System.currentTimeMillis() > EXPIRED_ON);
    }
}

Sonra diğer sınıflarda, kodun süresi dolmuşsa çıkabilirim. EXPIRED_ON değişkenine başka bir sınıftan atıfta bulunursam, sabit bayt koduyla aynı hizadadır ve bu da koddaki son kullanma tarihini kontrol eden tüm yerleri bulmayı çok zorlaştırır. Ancak, diğer sınıflar isExpired () yöntemini çağırırsa, gerçek yöntem çağrılır, yani bir bilgisayar korsanı isExpired yöntemini her zaman false döndüren başka bir yöntemle değiştirebilir.

Bir derleyiciyi statik son yöntemi kendisine başvuran tüm sınıflara satır içi yapmaya zorlamanın çok güzel olacağını kabul ediyorum. Bu durumda, çalışma zamanında gerekli olmayacağı için Control sınıfını dahil etmeniz bile gerekmez.

Araştırmamdan bu yapılamaz. Belki bazı Obfuscator araçları bunu yapabilir veya derlemeden önce kaynakları düzenlemek için derleme sürecinizi değiştirebilirsiniz.

Derleme sırasında kontrol sınıfındaki yöntemin başka bir sınıfa satır içi olarak yerleştirilip yerleştirilmediğini kanıtlamaya gelince, diğer sınıfı sınıf yolunda Control sınıfı olmadan çalıştırmayı deneyin.


2

Pekala, javada "satır içi" olarak adlandırılabilecek yöntemler vardır, ancak jvm'ye bağlıdır. Derlemeden sonra, yöntemin makine kodu 35 bayttan az ise, hemen bir satır içi yönteme aktarılacaktır, yöntemin makine kodu 325 bayttan küçükse, jvm'ye bağlı olarak bir satır içi yönteme aktarılabilir.


1
Bunlar Oracle VM için varsayılan değerlerdir, bkz. Docs.oracle.com/javase/8/docs/technotes/tools/unix/java.html
rmuller

0

yani, yok gibi görünüyor, ancak bu geçici çözümü guava veya eşdeğer bir Function sınıfı uygulaması kullanarak kullanabilirsiniz, çünkü bu sınıf son derece basittir, örn .:

    assert false : new com.google.common.base.Function<Void,String>(){
        @Override public String apply(Void input) {
            //your complex code go here
            return "weird message";
        }}.apply(null);

evet, bu sadece karmaşık bir kod bloğunun nasıl oluşturulacağını ({} içinde), bunun için herhangi bir yöntem oluşturmada bizi rahatsız etmemesi gereken çok özel bir şeyi nasıl yapacağımızı örneklemek için ölü koddur, AKA inline!


Makul bir fikir gibi görünüyor. Bunun google ortak kitaplıklarını kullanmayan bir sürümüne sahip misiniz?
ragerdl

0

Java9, satır içi olarak görülebilen çalışma zamanı yerine derleme zamanında birkaç optimizasyon yapan "Zamanın ilerisinde" bir derleyiciye sahiptir.

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.