Bagaimana cara meningkatkan kinerja aplikasi yang menggunakan operasi JAXBContext.newInstance?

Saya menggunakan operasi JAXBContext.newInstance di aplikasi web berbasis JBoss saya. Operasi ini, setahu saya, sangat berat. Saya hanya memerlukan dua instance unik dari kelas Marshaller.

Proposal awal saya adalah memiliki blok penginisialisasi statis yang akan menginisialisasi dua contoh ini hanya sekali saat kelas dimuat:

public class MyWebApp {
    private static Marshaller requestMarshaller;
    private static Marshaller responseMarshaller;

    static {
        try {
            // one time instance creation
            requestMarshaller = JAXBContext.newInstance(Request.class).createMarshaller();
            responseMarshaller = JAXBContext.newInstance(Response.class).createMarshaller();
        } catch (JAXBException e) {
            e.printStackTrace();
        }
    }

    private void doSomething() {
            requestMarshaller.marshall(...);
            responseMarshaller.marshall(...);
            ...
    }

}

Jika ini adalah solusi yang masuk akal maka saya kira saya akan menjawab pertanyaan saya sendiri, tapi saya ingin tahu apakah ini cara yang benar untuk melakukan ini?


person ryan    schedule 18.05.2011    source sumber


Jawaban (5)


Implementasi JAXB (Metro, EclipseLink MOXy, Apache JaxMe, dll) biasanya menginisialisasi metadatanya selama panggilan JAXBContext.newInstance. Semua alat OXM perlu menginisialisasi metadata pemetaan pada titik tertentu dan mencoba meminimalkan biaya operasi ini. Karena tidak mungkin melakukannya tanpa biaya, yang terbaik adalah melakukannya sekali saja. Contoh JAXBContext aman untuk thread, jadi ya, Anda hanya perlu membuatnya sekali.

Dari Spesifikasi JAXB 2.2, Bagian 4.2 Konteks JAXB :

Untuk menghindari overhead yang terlibat dalam pembuatan instance JAXBContext, aplikasi JAXB dianjurkan untuk menggunakan kembali instance JAXBContext. Implementasi kelas abstrak JAXBContext harus thread-safe, sehingga beberapa thread dalam suatu aplikasi dapat berbagi instance JAXBContext yang sama.

Instance Marshaller dan Unmarshaller tidak aman untuk thread dan tidak boleh dibagikan antar thread, karena keduanya ringan untuk dibuat.

person bdoughan    schedule 18.05.2011

JAXBContext harus selalu statis, aman untuk thread.

Marshallers dan Unmarshallers murah dan tidak aman untuk thread. Anda harus membuat JAXBContext sekali dan membuat marshaller/unmarshallers untuk setiap operasi

public class MyWebApp {
    private static JAXBContext jaxbContext;

    static {
        try {
            // one time instance creation
            jaxbContext = JAXBContext.newInstance(Request.class, Response.class);
        } catch (JAXBException e) {
            throw new IllegalStateException(e);
        }
    }

    private void doSomething() {                
            jaxbContext.createMarshaller().marshall(...);
            ...
    }

}

Gunakan marshaller yang sama untuk menyusun semuanya (tambahkan semua kelas saat Anda membuat konteks).

person cocorossello    schedule 03.07.2014
comment
Sekadar komentar: Anda tidak boleh menggunakan kembali marshaller/unmarshallers, mereka tidak aman untuk thread. Buat saja setiap saat, ini sangat cepat - person cocorossello; 03.06.2015
comment
Saya pikir solusi yang disarankan di sini tepat, dan sangat membantu, tapi saya tidak percaya contoh kode menggambarkan poin yang dibuat dalam teks bahwa Anda tidak boleh memanggil JAXBContext.newInstance() setiap kali Anda membutuhkan Marshaller . Bukankah seharusnya baris di doSomething() menjadi requestMarshaller = jaxbContext.createMarshaller();? - person rscarter; 23.09.2015

Saya baru-baru ini melakukan beberapa pengujian kinerja dengan JAXBContext.newInstance dan hasilnya didokumentasikan di sini.

http://app-inf.blogspot.com/2012/10/kinerja-tuning-logging-right-way.html

Saat dipanggil oleh satu thread, menggunakan skema yang cukup besar dengan ~195 kelas yang dihasilkan, diperlukan waktu ~400 md untuk menyelesaikannya. Saat dipanggil oleh 20 thread secara bersamaan, hal ini menyebabkan pertikaian CPU, dan membutuhkan waktu hingga ~5000 ms untuk menyelesaikannya. Pembuatan marshaller dan serialisasi objek dari objek kecil hanya terlalu ~14ms.

person user1738754    schedule 11.10.2012

Seseorang dapat menggunakan javax.xml.bind.JAXB. Ia memiliki metode marshal langsung dan metode tidak marshal. Jadi Anda tidak perlu khawatir tentang pembuatan instance JAXB.

misalnya JAXB.unmarshal(inputStream/inputFile, outputClassExpected) atau JAXB.marshal(jaxbObject, xmlOutputFile/xmlOutputStream)

person sandeep kale    schedule 28.03.2016
comment
Apakah Anda melihat ini di javadoc kelas javax .xml.bind.JAXB? Secara umum, kinerjanya belum tentu optimal. Diharapkan orang-orang yang perlu menulis kode penting kinerja akan menggunakan API JAXB lainnya secara langsung. - person Thomas Fritsch; 11.09.2017
comment
@ThomasFritsch, Ya. Kinerja mungkin menjadi perhatian untuk proyek-proyek penting. Ini harus diperiksa jika memang demikian. Mungkin menulis marshaller/un-marshaller sendiri akan membantu. - person sandeep kale; 14.09.2017
comment
Dalam kasus saya JAXB.marshall menggunakan implementasi cache konteksnya sendiri. Oracle JDK 8. Jadi ternyata lebih cepat daripada menggunakan Jaxb API dan tidak melakukan caching konteksnya - person Filip; 14.03.2019

Anda harus membuat objek JAXBContext tunggal per kelas kacang. lihat ini

person Nitin    schedule 10.04.2018