Rumah  >  Artikel  >  Java  >  Penemubual: Mengapakah pemuat kelas tomcat melanggar model perwakilan ibu bapa?

Penemubual: Mengapakah pemuat kelas tomcat melanggar model perwakilan ibu bapa?

Java后端技术全栈
Java后端技术全栈ke hadapan
2023-08-17 14:36:381092semak imbas

. .

Tetapi jika anda bertanya lebih dalam, lebih dalam sedikit, anda boleh menyejukkan sebilangan besar orang.
Contohnya: Mengapakah pemuat kelas tomcat melanggar model perwakilan ibu bapa?

Untuk mengelakkan anda daripada menghadapi situasi seperti ini semasa temuduga, artikel ini akan mengaturkan perkara ini.

Kami akan membincangkannya dalam 4 bahagian:

Apakah mekanisme pemuatan kelas?

  1. Apakah Model Pelantikan Ibu Bapa?
  2. Bagaimana untuk memecahkan model delegasi ibu bapa?
  3. Bagaimanakah pemuat kelas Tomcat direka?
  4. Saya fikir, sebelum mengkaji pemuatan kelas tomcat, kita harus menyemak atau menyatukan pemuat kelas lalai java. Semasa saya mula belajar JVM, saya keliru tentang mekanisme pemuatan kelas, jadi saya ingin mengambil peluang ini untuk berkongsi dengan anda.
  5. 1. Apakah mekanisme pemuatan kelas?

Menukar hasil kompilasi kod daripada kod mesin tempatan kepada kod bait ialah satu langkah kecil dalam format storan, tetapi satu langkah besar dalam pembangunan bahasa pengaturcaraan.

Mesin maya Java memuatkan data yang menerangkan kelas daripada fail Kelas ke dalam memori, mengesahkan data, menukar, menghuraikan dan memulakan data, dan akhirnya membentuk jenis Java yang boleh digunakan secara langsung oleh mesin maya mekanisme pemuatan kelas mesin maya.

Pasukan reka bentuk mesin maya melaksanakan tindakan "mendapatkan aliran bait binari yang menerangkan kelas ini melalui nama kelas yang layak sepenuhnya" dalam fasa pemuatan kelas di luar mesin maya Java, supaya aplikasi boleh memutuskan cara melakukannya Dapatkan kelas yang diperlukan. Modul kod yang melaksanakan tindakan ini dipanggil "pemuat kelas".

Hubungan antara kelas dan pemuat kelas

Walaupun pemuat kelas hanya digunakan untuk melaksanakan tindakan pemuatan kelas, peranannya dalam program Java jauh daripada terhad kepada peringkat pemuatan kelas. Untuk mana-mana kelas, pemuat kelas yang memuatkannya dan kelas itu sendiri perlu mewujudkan keunikannya dalam mesin maya Java Setiap pemuat kelas mempunyai ruang nama kelas bebas.

Ayat ini boleh dinyatakan dengan cara yang lebih popular: membandingkan sama ada dua kelas adalah "sama" hanya masuk akal jika kedua-dua kelas dimuatkan oleh pemuat kelas yang sama dimuatkan oleh mesin maya yang sama selagi pemuat kelas yang memuatkannya berbeza, kedua-dua kelas itu mestilah tidak sama.

2 Apakah Model Delegasi Ibu Bapa

1 Dari perspektif mesin maya Java, hanya terdapat dua pemuat kelas yang berbeza: satu ialah Bootstrap ClassLoader, yang menggunakan bahasa C++ Pelaksanaan (HotSpot sahaja) adalah sebahagian. daripada mesin maya itu sendiri; yang lain ialah semua pemuat kelas lain, yang dilaksanakan dalam bahasa Java, bebas daripada mesin maya, dan semuanya mewarisi daripada kelas abstrakjava.lang.ClassLoader.

2 Dari perspektif pembangun Java, pemuatan kelas boleh dibahagikan kepada butiran lanjut Kebanyakan pengaturcara Java akan menggunakan tiga pemuat kelas berikut yang disediakan oleh sistem:

  • Bootstrap ClassLoader: Kompleks pemuat kelas ini akan disimpan dalam direktori JAVA_HOME/lib atau dalam laluan yang ditentukan oleh parameter -Xbootclasspath, dan diiktiraf oleh mesin maya (hanya mengikut pengecaman Nama fail, seperti rt.jar, perpustakaan kelas dengan nama yang tidak konsisten tidak akan dibebankan walaupun ia diletakkan dalam direktori lib).
  • Extension ClassLoader: Pemuat kelas ini terdiri daripada sun.misc.Launcher$ExtClassLoader, yang bertanggungjawab untuk mencampurkan semua perpustakaan kelas dalam direktori JAVA_HOME/lib/ext atau dalam laluan yang ditentukan oleh pembolehubah sistem java.ext.dirs . Pembangun boleh menggunakan pemuat kelas sambungan secara langsung. sun.misc.Launcher$ExtClassLoader实现,它负责夹杂JAVA_HOME/lib/ext 目录下的,或者被java.ext.dirs 系统变量所指定的路径中的所有类库。开发者可以直接使用扩展类加载器。
  • 应用程序类加载器(Application ClassLoader): 这个类加载器由sun.misc.Launcher$AppClassLoader

Application ClassLoader:

Pemuat kelas ini terdiri daripada sun.misc.Launcher$AppClassLoaderpelaksanaan. Memandangkan pemuat kelas ini ialah nilai pulangan kaedah getSystemClassLoader dalam ClassLoader, ia juga menjadi pemuat kelas sistem. Ia bertanggungjawab untuk memuatkan perpustakaan kelas yang ditentukan pada laluan kelas pengguna (ClassPath). Pembangun boleh menggunakan pemuat kelas ini secara langsung Jika aplikasi tidak mentakrifkan pemuat kelasnya sendiri, ini biasanya pemuat kelas lalai dalam program.
Penemubual: Mengapakah pemuat kelas tomcat melanggar model perwakilan ibu bapa?
Hubungan antara pemuat kelas ini secara amnya seperti yang ditunjukkan dalam rajah di bawah:

gambar

Hubungan antara setiap pemuat kelas dalam rajah dipanggil

Model perwakilan ibu bapa pemuat kelas
). Model delegasi induk memerlukan bahawa sebagai tambahan kepada pemuat kelas permulaan peringkat atas, semua pemuat kelas lain harus dimuatkan oleh pemuat kelas induk mereka sendiri Hubungan induk-anak antara pemuat kelas di sini secara amnya tidak direalisasikan melalui warisan, tetapi melalui pewarisan. . Mereka semua menggunakan perhubungan komposisi untuk menggunakan semula kod pemuat induk.

🎜Nota: Semasa temu duga, penemuduga juga boleh bertanya direktori mana yang dimuatkan oleh pemuat kelas yang sepadan. 🎜🎜🎜Model delegasi induk pemuat kelas telah diperkenalkan semasa JDK1.2 dan digunakan secara meluas dalam semua program Java berikutnya Walau bagaimanapun, ia bukan model kekangan mandatori, tetapi disyorkan oleh pereka bentuk Java kepada pelaksanaan pemuat kelas. 🎜

Proses kerja model perwakilan induk ialah: jika pemuat kelas menerima permintaan pemuatan kelas, ia tidak akan cuba memuatkan kelas itu sendiri terlebih dahulu, tetapi mewakilkan permintaan itu kepada pemuat kelas induk untuk diselesaikan. Ini benar untuk setiap peringkat pemuat kelas, jadi semua permintaan pemuatan akhirnya harus dihantar ke pemuat kelas permulaan peringkat atas Hanya apabila pemuat induk memberi maklum balas bahawa ia tidak dapat menyelesaikan permintaan (permintaan yang diperlukan tidak ditemui dalam skop cariannya ) kelas), subloader akan cuba memuatkannya dengan sendirinya.

Kenapa awak buat macam ni?

Jika model delegasi induk tidak digunakan dan setiap pemuat kelas memuatkannya dengan sendirinya, jika pengguna menulis kelas yang dipanggil java.lang.Object dan meletakkannya dalam ClassPath program, sistem akan mempunyai beberapa perbezaan kelas , tingkah laku paling asas dalam sistem jenis Java tidak boleh dijamin. Permohonan juga akan menjadi kucar-kacir.

Bagaimana model delegasi ibu bapa dilaksanakan? . tidak, panggil kaedah LoadClass pemuat induk pemuat Jika pemuat induk kosong, pemuat kelas permulaan akan digunakan sebagai pemuat induk secara lalai. Jika kelas induk gagal dimuatkan, buang pengecualian ClassNotFoundException dan kemudian panggil kaedah findClass sendiri untuk memuatkannya.

java.lang.ClassLoader3. Bagaimana untuk memecahkan model delegasi ibu bapa?

Kami baru sahaja mengatakan bahawa model delegasi induk bukanlah model kekangan mandatori, tetapi pelaksanaan pemuat kelas yang dicadangkan. Kebanyakan pemuat kelas di dunia Java mengikuti model ini, tetapi terdapat pengecualian setakat ini, model delegasi ibu bapa telah "pecah" secara besar-besaran tiga kali. Penemubual: Mengapakah pemuat kelas tomcat melanggar model perwakilan ibu bapa?
Kali pertama: sebelum kemunculan model delegasi ibu bapa-----sebelum keluaran JDK1.2.

Kali kedua: Ia disebabkan oleh kecacatan model ini sendiri.
Kami mengatakan bahawa model delegasi induk menyelesaikan masalah menyatukan kelas asas setiap pemuat kelas (semakin banyak kelas asas dimuatkan oleh pemuat peringkat atas Sebab mengapa kelas asas dipanggil "asas" adalah kerana mereka Ia sentiasa API yang dipanggil oleh kod pengguna, tetapi tiada jaminan Bagaimana jika kelas asas memanggil kod pengguna?

Ini tidak mustahil. Contoh biasa ialah perkhidmatan JNDI kini merupakan perkhidmatan standard dalam Java Kodnya dimuatkan oleh pemuat kelas permulaan (rt.jar yang diletakkan dalam JDK1.3), tetapi ia perlu dipanggil dan dilaksanakan oleh bebas. vendor. Dan gunakan kod penyedia antara muka JNDI (SPI, Antara Muka Pembekal Perkhidmatan) di bawah ClassPath aplikasi, tetapi adalah mustahil untuk pemuat kelas permulaan untuk "mengecam" kod ini. Kerana kelas ini tiada dalam rt.jar , Tetapi pemuat kelas permulaan perlu dimuatkan semula. Apa yang perlu dilakukan? rt.jar中,但是启动类加载器又需要加载。怎么办呢?

为了解决这个问题,Java设计团队只好引入了一个不太优雅的设计:线程上下文类加载器(Thread Context ClassLoader)。这个类加载器可以通过java.lang.Thread

Untuk menyelesaikan masalah ini, pasukan reka bentuk Java terpaksa memperkenalkan reka bentuk yang kurang elegan: Thread Context ClassLoader. Pemuat kelas ini boleh diluluskan ,35,.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(239, 112, 96);">java .lang.Thread Kaedah setContextClassLoader bagi kod> kelas ditetapkan. Jika ia belum ditetapkan semasa utas dicipta, ia akan mewarisi satu daripada utas induk Jika tidak ditetapkan terlalu banyak dalam skop global aplikasi, maka pemuat kelas ini akan lalai kepada pemuat kelas aplikasi.

Hei, dengan pemuat konteks utas, perkhidmatan JNDI menggunakan pemuat konteks utas ini untuk memuatkan kod SPI yang diperlukan, iaitu, pemuat kelas induk meminta pemuat kelas kanak-kanak untuk melengkapkan tindakan pemuatan kelas Ini sebenarnya Ia baru sahaja dibuka naikkan struktur hierarki model perwakilan ibu bapa untuk menggunakan pemuat kelas secara terbalik, yang sebenarnya melanggar prinsip umum model perwakilan ibu bapa. Tetapi tiada apa yang boleh anda lakukan mengenainya Semua tindakan memuatkan yang melibatkan SPI dalam Java pada asasnya menggunakan kaedah ini. Contohnya JNDI, JDBC, JCE, JAXB, JBI, dll.

Kali ketiga: Untuk mencapai palam panas, penggunaan panas dan modularisasi, yang bermaksud menambah fungsi atau menolak fungsi tanpa dimulakan semula, anda hanya perlu menggantikan modul bersama-sama dengan pemuat kelas untuk mencapai penggantian kod panas.

Buku itu juga berkata:

Pada asasnya terdapat konsensus dalam program Java: Penggunaan OSGI pemuat kelas adalah berbaloi untuk dipelajari Memahami pelaksanaan OSGI boleh dianggap sebagai menguasai intipati pemuat kelas.

Hebat! ! !

Kini, kami pada asasnya telah memahami prinsip kerja pemuatan kelas lalai Java, dan kami juga mengetahui model perwakilan induk. Setelah berkata begitu banyak, saya hampir terlupa tentang kucing jantan kami. Topik kami ialah mengapa pemuat Tomcat melanggar model perwakilan ibu bapa?

Mari kita bercakap tentang pemuat kelas tomcat kami.

4 Bagaimanakah pemuat kelas Tomcat direka?

Mula-mula, mari kita ajukan soalan:

Adakah wajar jika Tomcat menggunakan mekanisme pemuatan kelas lalai?

🎜

Mari kita fikirkan: Tomcat ialah bekas web, jadi apakah masalah yang perlu diselesaikannya:

  • Sebuah bekas web mungkin perlu menggunakan dua aplikasi dan aplikasi yang berbeza mungkin bergantung pada versi berbeza kelas pihak ketiga yang sama perpustakaan. Ia tidak boleh Diperlukan bahawa hanya terdapat satu salinan perpustakaan kelas yang sama pada pelayan yang sama, jadi adalah perlu untuk memastikan bahawa perpustakaan kelas setiap aplikasi adalah bebas dan terpencil antara satu sama lain.
  • Pustaka kelas yang sama dan versi yang sama digunakan dalam bekas web yang sama boleh dikongsi. Jika tidak, jika pelayan mempunyai 10 aplikasi, maka 10 salinan perpustakaan kelas yang sama mesti dimuatkan ke dalam mesin maya, yang tidak masuk akal.
  • Bekas web juga mempunyai perpustakaan kelas bergantungnya sendiri, yang tidak boleh dikelirukan dengan perpustakaan kelas aplikasi. Atas sebab keselamatan, perpustakaan kelas kontena harus diasingkan daripada perpustakaan kelas program.
  • Bekas web mesti menyokong pengubahsuaian jsp program dijalankan. Jika tidak, apa gunanya anda? Oleh itu, bekas web perlu menyokong pengubahsuaian jsp tanpa dimulakan semula.

Mari lihat soalan kami sekali lagi: Adakah boleh jika Tomcat menggunakan mekanisme pemuatan kelas lalai?

Jawapannya tidak. kenapa? Mari lihat masalah pertama Jika anda menggunakan mekanisme pemuat kelas lalai, anda tidak boleh memuatkan dua versi berbeza bagi pustaka kelas yang sama salinan.

Soalan kedua ialah pemuat kelas lalai boleh dilaksanakan kerana tanggungjawabnya adalah untuk memastikan keunikan. Soalan ketiga sama dengan soalan pertama. Mari kita lihat soalan keempat sekali lagi. Kami fikir bagaimana kita melaksanakan pengubahsuaian panas fail jsp (nama yang diberikan oleh poster itu sebenarnya fail kelas Jadi jika ia diubah suai, tetapi nama kelas masih sama, pemuat kelas akan terus Jika jsp sudah wujud dalam kawasan kaedah diambil, jsp yang diubah suai tidak akan dimuat semula.

Jadi apa yang patut kita buat? Kami boleh menyahpasang secara langsung pemuat kelas bagi fail jsp ini, jadi anda sepatutnya berfikir bahawa setiap fail jsp sepadan dengan pemuat kelas yang unik Apabila fail jsp diubah suai, pemuat kelas jsp dipunggah terus. Buat semula pemuat kelas dan muat semula fail jsp.

Bagaimanakah Tomcat melaksanakan mekanisme pemuatan kelasnya yang unik?

Jadi, bagaimanakah Tomcat melaksanakannya? Pasukan Tomcat yang hebat telah mereka bentuknya. Mari lihat lukisan reka bentuk mereka:

Penemubual: Mengapakah pemuat kelas tomcat melanggar model perwakilan ibu bapa?
Picture

Kami melihat bahawa tiga pemuatan kelas pertama adalah konsisten dengan yang lalai CommonClassLoader, CatalinaClassLoader, SharedClassLoader dan WebappClassLoader adalah pemuat kelas Tomcat sendiri, masing-masing dalam kelas pemuat Web laluan pemuatan hanya boleh dilihat oleh Webapp semasa; /common/*/server/*/shared/*(在tomcat 6之后已经合并到根目录下的lib目录下)和/WebApp/WEB-INF/*中的Java类库。其中WebApp类加载器和Jsp类加载器通常会存在多个实例,每一个Web应用程序对应一个WebApp类加载器,每一个JSP文件对应一个Jsp类加载器。

  • commonLoader:Tomcat最基本的类加载器,加载路径中的class可以被Tomcat容器本身以及各个Webapp访问;
  • catalinaLoader:Tomcat容器私有的类加载器,加载路径中的class对于Webapp不可见;
  • sharedLoader:各个Webapp共享的类加载器,加载路径中的class对于所有Webapp可见,但是对于Tomcat容器不可见;
  • WebappClassLoader
Ia boleh dilihat daripada perhubungan delegasi dalam rajah:

Kelas yang boleh dimuatkan oleh CommonClassLoader boleh digunakan oleh Catalina ClassLoader dan SharedClassLoader, dengan itu merealisasikan penggunaan perpustakaan kelas awam Shared, manakala kelas yang CatalinaClassLoader dan Shared ClassLoader boleh dimuatkan diasingkan antara satu sama lain.

WebAppClassLoader boleh menggunakan kelas yang dimuatkan oleh SharedClassLoader, tetapi kejadian WebAppClassLoader individu diasingkan antara satu sama lain.

Skop pemuatan JasperLoader hanyalah fail .Class yang disusun oleh fail JSP ini Tujuan penampilannya adalah untuk dibuang: apabila bekas web mengesan bahawa fail JSP telah diubah suai, ia akan menggantikan tika JasperLoader semasa. , dan melaksanakan fungsi HotSwap fail JSP dengan mencipta pemuat kelas Jsp baharu.

Baiklah, setakat ini, kita sudah tahu mengapa tomcat direka dengan cara ini dan bagaimana ia direka Jadi, adakah tomcat melanggar model delegasi ibu bapa yang disyorkan oleh Java? Jawapannya: dilanggar.

Kami berkata sebelum ini:

Model delegasi induk memerlukan bahawa kecuali pemuat kelas permulaan peringkat atas, semua pemuat kelas lain harus dimuatkan oleh pemuat kelas induk mereka sendiri.

Jelas sekali, tomcat tidak dilaksanakan dengan cara ini Untuk mencapai pengasingan, tomcat tidak mematuhi konvensyen ini Setiap webappClassLoader memuatkan fail kelas dalam direktorinya sendiri dan tidak akan menyerahkannya kepada pemuat kelas induk.

Kami melanjutkan soalan: Apakah yang perlu kami lakukan jika Common ClassLoader tomcat mahu memuatkan kelas dalam WebApp ClassLoader? Selepas membaca kandungan sebelumnya tentang memusnahkan model delegasi induk, kami mempunyai idea yang jelas tindakan memuatkan.

Bukankah ia hebat?

Ringkasan

Baiklah, akhirnya, kami faham mengapa Tomcat melanggar model delegasi induk, dan kami juga tahu cara pemuat kelas tomcat direka. Dengan cara ini, saya menyemak mekanisme pemuat kelas lalai Java, dan juga mempelajari cara memusnahkan mekanisme pemuatan kelas Java. Kali ini hasil tuaian bukan sedikit! ! !

Atas ialah kandungan terperinci Penemubual: Mengapakah pemuat kelas tomcat melanggar model perwakilan ibu bapa?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:Java后端技术全栈. Jika ada pelanggaran, sila hubungi admin@php.cn Padam