Jadual Kandungan
Pengenalan
Apakah itu JAR
Pengenalan JAR
Struktur JAR
Struktur pakej
Fail penerangan MANIFEST.MF
打包结果
启动时的类加载原理
启动的整个流程
Rumah Java javaTutorial Apakah FatJar dan Jar dalam Springboot?

Apakah FatJar dan Jar dalam Springboot?

May 11, 2023 am 09:58 AM
jar springboot fatjar

    Pengenalan

    Aplikasi Spring Boot boleh dibungkus dengan cepat menggunakan spring-boot-maven-plugin untuk membina balang boleh laku. Spring Boot mempunyai bekas terbenam, dan aplikasi boleh dimulakan terus melalui perintah java -jar.

    Walaupun ia adalah arahan permulaan yang mudah, terdapat banyak pengetahuan yang tersembunyi di sebaliknya. Hari ini saya akan membawa anda meneroka prinsip di sebalik permulaan FAT JAR. Artikel ini terutamanya mengandungi bahagian berikut:

    • Apakah itu JAR. Pertama, anda perlu memahami apa itu balang sebelum anda mengetahui apa yang java -jar lakukan.

    • Apa yang membezakan FatJar. Apakah perbezaan antara balang boleh laku yang disediakan oleh Spring Boot dan balang biasa?

    • Prinsip pemuatan kelas pada permulaan. Apakah yang dilakukan oleh pemuat kelas semasa permulaan? Bagaimanakah Spring Boot menyelesaikan masalah pemuatan pakej terbenam melalui pemuat kelas tersuai.

    • Keseluruhan proses dimulakan. Akhir sekali, sepadukan kandungan tiga bahagian sebelumnya dan analisis kod sumber untuk melihat cara melengkapkan permulaan.

    Apakah itu JAR

    Pengenalan JAR

    Fail JAR (Arkib Java, Bahasa Inggeris: Java ARchive) ialah format fail pakej perisian yang biasanya digunakan untuk mengagregat sejumlah besar fail kelas Java, metadata dan fail sumber (teks, imej, dll.) yang berkaitan ke dalam satu fail untuk mengedarkan perisian aplikasi platform Java atau perpustakaan . Untuk memahaminya secara ringkas, ia sebenarnya adalah pakej termampat Memandangkan ia adalah pakej termampat, untuk mengekstrak kandungan fail JAR, anda boleh menggunakan mana-mana perisian penyahmampatan standard untuk mengekstrak kandungan. Atau gunakan perintah terbina dalam mesin maya Java jar -xf foo.jar untuk menyahmampat fail balang yang sepadan.

    JAR boleh dibahagikan kepada dua kategori:

    • JAR tidak boleh laku. Semasa pembungkusan, anda tidak perlu menyatakan main-class dan ia tidak boleh dijalankan. Pakej balang biasa boleh digunakan oleh projek lain untuk bergantung.

    • JAR Boleh Laksana. Apabila membina pakej jar, jika kelas main-class ditentukan, anda boleh menggunakan perintah java -jar xxx.jar untuk melaksanakan kaedah main-class main untuk menjalankan pakej jar. Pakej balang boleh dijalankan tidak boleh dipercayai oleh projek lain.

    Struktur JAR

    Struktur pakej

    Sama ada JAR tidak berdaya maju atau JAR boleh laku, ia mengandungi dua bahagian selepas penyahmampatan: META-INF Direktori (metadata ) dan package direktori (kelas tersusun). Balang biasa ini tidak mengandungi pakej pergantungan pihak ketiga, tetapi hanya fail konfigurasi aplikasi sendiri, kelas, dsb.

    .
    ├── META-INF
    │   ├── MANIFEST.MF  #定义
    └── org  # 包路径(存放编译后的class)
        └── springframework
    Salin selepas log masuk
    Fail penerangan MANIFEST.MF

    Fail konfigurasi pakej JAR ialah fail META-INF dalam folder MANIFEST.MF. Maklumat konfigurasi utama adalah seperti berikut:

    • Versi Manifest: digunakan untuk menentukan versi fail manifes, contohnya: Versi Manifest: 1.0

    • Dicipta-Oleh: Isytiharkan penjana fail Secara amnya, atribut ini dijana oleh alat baris arahan jar, contohnya: Created-Oleh: Apache Ant 1.5.1

      <. 🎜>
    • Signature-Version: Tentukan versi tandatangan fail jar

    • Class-Path: Aplikasi atau pemuat kelas menggunakan nilai ini untuk membina carian kelas dalaman laluan, yang perlu ditetapkan dalam pakej balang boleh laku ini.

    Di atas ialah atribut

    pakej balang biasa Dalam fail .MF pakej balang boleh dijalankan , terdapat juga. atau mian-class dan atribut lain. Jika anda bergantung pada pakej balang luaran, laluan lib dan maklumat lain juga akan dikonfigurasikan dalam fail MF. start-classUntuk maklumat lanjutLihat: Bagaimana maven menambah kandungan pada fail MANIFEST.MF

    Bagi direktori

    pakej runnable jar dan pakej balang biasa Tiada corak tetap tertentu untuk struktur Secara ringkasnya, tidak kira apa strukturnya, selepas mengkonfigurasi maklumat pakej balang dalam fail .MF, anda boleh menggunakan pakej balang seperti biasa.

    Apakah perbezaan antara FatJar

    Apakah itu FatJar?

    Balang biasa hanya mengandungi maklumat tentang balang semasa dan tidak mengandungi balang pihak ketiga. Apabila secara dalaman bergantung pada balang pihak ketiga, ralat akan dilaporkan jika dijalankan secara langsung Dalam kes ini, balang pihak ketiga perlu dibenamkan ke dalam balang boleh laku.

    Letakkan balang dan balang pihak ketiga yang bergantung kepada satu pakej ini ialah FatJar.

    SpringBoot FatJar Solution

    Untuk menyelesaikan masalah balang terbenam, satu set penyelesaian FatJar disediakan, yang masing-masing mentakrifkan Spring Bootstruktur direktori balang dan . Atas dasar menyusun dan menjana balang boleh laku, gunakan MANIFEST.MF mengikut standard pakej boleh laku Spring Boot spring-boot-maven-plugin untuk mendapatkan balang Boot Spring boleh laku. repackageMengikut jenis balang boleh laku, ia terbahagi kepada dua jenis: Balang boleh laku dan perang boleh laku.

    proses pembungkusan spring-boot-maven-plugin
    Oleh kerana tiada pengenalan atau penulisan eksplisit kelas berkaitan di mana-mana sahaja dalam projek SpringBoot kosong yang baru dibuat. Malah, untuk setiap projek SpringBoot yang baru dibuat, anda boleh melihat pemalam berikut dalam fail pom.xmlnya:

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
    Salin selepas log masuk

    这个是SpringBoot官方提供的用于打包FatJar的插件,org.springframework.boot.loader下的类其实就是通过这个插件打进去的;

    下面是此插件将 loader 相关类打入 FatJar 的一个执行流程:

    org.springframework.boot.maven#execute->
    org.springframework.boot.maven#repackage -> org.springframework.boot.loader.tools.Repackager#repackage->
    org.springframework.boot.loader.tools.Repackager#writeLoaderClasses->
    org.springframework.boot.loader.tools.JarWriter#writeLoaderClasses
    Salin selepas log masuk

    最终的执行方法就是下面这个方法,通过注释可以看出,该方法的作用就是将 spring-boot-loader 的classes 写入到 FatJar 中。

    /**
     * Write the required spring-boot-loader classes to the JAR.
     * @throws IOException if the classes cannot be written
     */
    @Override
    public void writeLoaderClasses() throws IOException {
    	writeLoaderClasses(NESTED_LOADER_JAR);
    }
    Salin selepas log masuk
    打包结果

    Spring Boot项目被编译以后,在targert目录下存在两个jar文件:一个是xxx.jarxxx.jar.original

    • 其中xxx.jar.original是maven编译后的原始jar文件,即标准的java jar。该文件仅包含应用本地资源。 如果单纯使用这个jar,无法正常运行,因为缺少依赖的第三方资源。

    • 因此spring-boot-maven-plugin插件对这个xxx.jar.original再做一层加工,引入第三方依赖的jar包等资源,将其 "repackage"xxx.jar。可执行Jar的文件结构如下图所示:

    .
    ├── BOOT-INF
    │   ├── classes
    │   │   ├── application.properties  # 用户-配置文件
    │   │   └── com
    │   │       └── glmapper
    │   │           └── bridge
    │   │               └── boot
    │   │                   └── BootStrap.class  # 用户-启动类
    │   └── lib
    │       ├── jakarta.annotation-api-1.3.5.jar
    │       ├── jul-to-slf4j-1.7.28.jar
    │       ├── log4j-xxx.jar # 表示 log4j 相关的依赖简写
    ├── META-INF
    │   ├── MANIFEST.MF
    │   └── maven
    │       └── com.glmapper.bridge.boot
    │           └── guides-for-jarlaunch
    │               ├── pom.properties
    │               └── pom.xml
    └── org
        └── springframework
            └── boot
                └── loader
                    ├── ExecutableArchiveLauncher.class
                    ├── JarLauncher.class
                    ├── LaunchedURLClassLoader$UseFastConnectionExceptionsEnumeration.class
                    ├── LaunchedURLClassLoader.class
                    ├── Launcher.class
                    ├── MainMethodRunner.class
                    ├── PropertiesLauncher$1.class
                    ├── PropertiesLauncher$ArchiveEntryFilter.class
                    ├── PropertiesLauncher$PrefixMatchingArchiveFilter.class
                    ├── PropertiesLauncher.class
                    ├── WarLauncher.class
                    ├── archive
                    │   ├── # 省略
                    ├── data
                    │   ├── # 省略
                    ├── jar
                    │   ├── # 省略
                    └── util
                        └── SystemPropertyUtils.class
    Salin selepas log masuk
    • META-INF: 存放元数据。MANIFEST.MF 是 jar 规范,Spring Boot 为了便于加载第三方 jar 对内容做了修改;

    • org: 存放Spring Boot 相关类,比如启动时所需的 Launcher 等;

    • BOOT-INF/class: 存放应用编译后的 class 文件;

    • BOOT-INF/lib: 存放应用依赖的 JAR 包。

    Spring Boot的MANIFEST.MF和普通jar有些不同:

    Spring-Boot-Version: 2.1.3.RELEASE
    Main-Class: org.springframework.boot.loader.JarLauncher
    Start-Class: com.rock.springbootlearn.SpringbootLearnApplication
    Spring-Boot-Classes: BOOT-INF/classes/
    Spring-Boot-Lib: BOOT-INF/lib/
    Build-Jdk: 1.8.0_131
    Salin selepas log masuk

    Main-Class:java -jar启动引导类,但这里不是项目中的类,而是Spring Boot内部的JarLauncher
    Start-Class: 这个才是正在要执行的应用内部主类

    所以java -jar启动的时候,加载运行的是JarLauncher。Spring Boot内部如何通过JarLauncher 加载Start-Class 执行呢?为了更清楚加载流程,我们先介绍下java -jar是如何完成类加载逻辑的。

    启动时的类加载原理

    这里简单说下java -jar启动时是如何完成记载类加载的。Java 采用了双亲委派机制,Java语言系统自带有三个类加载器:

    • Bootstrap CLassloder: 最顶层的加载类,主要加载核心类库

    • Extention ClassLoader: 扩展的类加载器,加载目录%JRE_HOME%/lib/ext目录下的jar包和class文件。 还可以加载-D java.ext.dirs选项指定的目录。

    • AppClassLoader: 是应用加载器。

    默认情况下通过java -classpathjava -cpjava -jar使用的类加载器都是AppClassLoader。 普通可执行jar通过java -jar启动后,使用AppClassLoader加载Main-class类。 如果第三方jar不在AppClassLoader里,会导致启动时候会报ClassNotFoundException。

    例如在Spring Boot可执行jar的解压目录下,执行应用的主函数,就直接报该错误:

    Exception in thread "main" java.lang.NoClassDefFoundError: org/springframework/boot/SpringApplication
    at com.glmapper.bridge.boot.BootStrap.main(BootStrap.java:13)
    Caused by: java.lang.ClassNotFoundException: org.springframework.boot.SpringApplication
    at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:338)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    ... 1 more

    从异常堆栈来看,是因为找不到SpringApplication这个类;这里其实还是比较好理解的,BootStrap类中引入了SpringApplication,但是这个类是在BOOT-INF/lib下的,而java指令在启动时未指明classpath,依赖的第三方jar无法被加载。

    Spring Boot JarLauncher启动时,会将所有依赖的内嵌 jar (BOOT-INF/lib 目录下) 和class(BOOT-INF/classes 目录)都加入到自定义的类加载器LaunchedURLClassLoader中,并用这个ClassLoder去加载MANIFEST.MF配置Start-Class,则不会出现类找不到的错误。

    LaunchedURLClassLoader是URLClassLoader的子类, URLClassLoader会通过URL[] 来搜索类所在的位置。Spring Boot 则将所需要的内嵌文档组装成URL[],最终构建LaunchedURLClassLoader类。

    启动的整个流程

    有了以上知识的铺垫,我们看下整个 FatJar 启动的过程会是怎样。为了以便查看源码和远程调试,可以在 pom.xml 引入下面的配置:

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-loader</artifactId>
    </dependency>
    Salin selepas log masuk

    简单概括起来可以分为几步:

    • java -jar 启动,AppClassLoader 则会加载 MANIFEST.MF 配置的Main-Class, JarLauncher。

    • JarLauncher启动时,注册URL关联协议。

    • 获取所有内嵌的存档(内嵌jar和class)

    • 根据存档的URL[]构建类加载器。

    • 然后用这个类加载器加载Start-Class。 保证这些类都在同一个ClassLoader中。

    Atas ialah kandungan terperinci Apakah FatJar dan Jar dalam Springboot?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

    Kenyataan Laman Web ini
    Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn

    Alat AI Hot

    Undresser.AI Undress

    Undresser.AI Undress

    Apl berkuasa AI untuk mencipta foto bogel yang realistik

    AI Clothes Remover

    AI Clothes Remover

    Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

    Undress AI Tool

    Undress AI Tool

    Gambar buka pakaian secara percuma

    Clothoff.io

    Clothoff.io

    Penyingkiran pakaian AI

    AI Hentai Generator

    AI Hentai Generator

    Menjana ai hentai secara percuma.

    Artikel Panas

    R.E.P.O. Kristal tenaga dijelaskan dan apa yang mereka lakukan (kristal kuning)
    2 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌
    Repo: Cara menghidupkan semula rakan sepasukan
    4 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌
    Hello Kitty Island Adventure: Cara mendapatkan biji gergasi
    3 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌

    Alat panas

    Notepad++7.3.1

    Notepad++7.3.1

    Editor kod yang mudah digunakan dan percuma

    SublimeText3 versi Cina

    SublimeText3 versi Cina

    Versi Cina, sangat mudah digunakan

    Hantar Studio 13.0.1

    Hantar Studio 13.0.1

    Persekitaran pembangunan bersepadu PHP yang berkuasa

    Dreamweaver CS6

    Dreamweaver CS6

    Alat pembangunan web visual

    SublimeText3 versi Mac

    SublimeText3 versi Mac

    Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

    Bagaimana Springboot menyepadukan Jasypt untuk melaksanakan penyulitan fail konfigurasi Bagaimana Springboot menyepadukan Jasypt untuk melaksanakan penyulitan fail konfigurasi Jun 01, 2023 am 08:55 AM

    Pengenalan kepada Jasypt Jasypt ialah perpustakaan java yang membenarkan pembangun menambah fungsi penyulitan asas pada projeknya dengan usaha yang minimum dan tidak memerlukan pemahaman yang mendalam tentang cara penyulitan berfungsi dengan tinggi untuk penyulitan sehala dan dua hala. teknologi penyulitan berasaskan piawai. Sulitkan kata laluan, teks, nombor, perduaan... Sesuai untuk penyepaduan ke dalam aplikasi berasaskan Spring, API terbuka, untuk digunakan dengan mana-mana pembekal JCE... Tambahkan kebergantungan berikut: com.github.ulisesbocchiojasypt-spring-boot-starter2 Faedah Jasypt melindungi keselamatan sistem kami Walaupun kod itu bocor, sumber data boleh dijamin.

    Bagaimana untuk menjalankan fail jar di Linux Bagaimana untuk menjalankan fail jar di Linux Feb 20, 2024 am 10:40 AM

    Prasyarat untuk menjalankan fail JAR Menjalankan fail JAR pada sistem Linux memerlukan pemasangan Java Runtime Environment (JRE), yang merupakan komponen asas yang diperlukan untuk melaksanakan aplikasi Java, termasuk Java Virtual Machine (JVM), perpustakaan kelas teras, dsb. Banyak pengedaran Linux arus perdana, seperti Ubuntu, Debian, Fedora, openSUSE, dll., menyediakan perpustakaan perisian pakej JRE untuk memudahkan pemasangan pengguna. Artikel berikut akan memperincikan langkah-langkah untuk memasang JRE pada pengedaran popular. Selepas menyediakan JRE, anda boleh memilih untuk menggunakan terminal baris arahan atau antara muka pengguna grafik untuk memulakan fail JAR mengikut keutamaan peribadi anda. Pilihan anda mungkin bergantung pada kebiasaan dengan cangkerang Linux dan keutamaan peribadi

    Cara menggunakan Redis untuk melaksanakan kunci teragih dalam SpringBoot Cara menggunakan Redis untuk melaksanakan kunci teragih dalam SpringBoot Jun 03, 2023 am 08:16 AM

    1. Redis melaksanakan prinsip kunci teragih dan mengapa kunci teragih diperlukan Sebelum bercakap tentang kunci teragih, adalah perlu untuk menjelaskan mengapa kunci teragih diperlukan. Lawan daripada kunci yang diedarkan ialah kunci yang berdiri sendiri Apabila kami menulis program berbilang benang, kami mengelakkan masalah data yang disebabkan oleh mengendalikan pembolehubah yang dikongsi pada masa yang sama Kami biasanya menggunakan kunci untuk mengecualikan pembolehubah yang dikongsi bersama untuk memastikan ketepatannya pembolehubah yang dikongsi skop penggunaannya adalah dalam proses yang sama. Jika terdapat berbilang proses yang perlu mengendalikan sumber yang dikongsi pada masa yang sama, bagaimanakah ia boleh saling eksklusif? Aplikasi perniagaan hari ini biasanya merupakan seni bina perkhidmatan mikro, yang juga bermakna bahawa satu aplikasi akan menggunakan berbilang proses Jika berbilang proses perlu mengubah suai baris rekod yang sama dalam MySQL, untuk mengelakkan data kotor yang disebabkan oleh operasi yang tidak teratur, keperluan pengedaran. untuk diperkenalkan pada masa ini. Gaya dikunci. Ingin mencapai mata

    Bagaimana SpringBoot menyepadukan Redisson untuk melaksanakan baris gilir kelewatan Bagaimana SpringBoot menyepadukan Redisson untuk melaksanakan baris gilir kelewatan May 30, 2023 pm 02:40 PM

    Senario penggunaan 1. Tempahan berjaya dibuat tetapi pembayaran tidak dibuat dalam masa 30 minit. Pembayaran tamat masa dan pesanan dibatalkan secara automatik 2. Pesanan telah ditandatangani dan tiada penilaian dilakukan selama 7 hari selepas ditandatangani. Jika pesanan tamat dan tidak dinilai, sistem lalai kepada penilaian positif 3. Pesanan dibuat dengan jayanya jika peniaga tidak menerima pesanan selama 5 minit, pesanan itu dibatalkan peringatan mesej teks dihantar... Untuk senario dengan kelewatan yang lama dan prestasi masa nyata yang rendah, kami boleh Gunakan penjadualan tugas untuk melaksanakan pemprosesan undian biasa. Contohnya: xxl-job Hari ini kita akan memilih

    Analisis perbandingan dan perbezaan antara SpringBoot dan SpringMVC Analisis perbandingan dan perbezaan antara SpringBoot dan SpringMVC Dec 29, 2023 am 11:02 AM

    SpringBoot dan SpringMVC adalah kedua-dua rangka kerja yang biasa digunakan dalam pembangunan Java, tetapi terdapat beberapa perbezaan yang jelas antara mereka. Artikel ini akan meneroka ciri dan penggunaan kedua-dua rangka kerja ini dan membandingkan perbezaannya. Mula-mula, mari belajar tentang SpringBoot. SpringBoot telah dibangunkan oleh pasukan Pivotal untuk memudahkan penciptaan dan penggunaan aplikasi berdasarkan rangka kerja Spring. Ia menyediakan cara yang pantas dan ringan untuk membina bersendirian, boleh dilaksanakan

    Bagaimana untuk menyelesaikan masalah bahawa springboot tidak boleh mengakses fail selepas membacanya ke dalam pakej balang Bagaimana untuk menyelesaikan masalah bahawa springboot tidak boleh mengakses fail selepas membacanya ke dalam pakej balang Jun 03, 2023 pm 04:38 PM

    Springboot membaca fail, tetapi tidak boleh mengakses perkembangan terkini selepas membungkusnya ke dalam pakej balang Terdapat situasi di mana springboot tidak boleh membaca fail selepas membungkusnya ke dalam pakej balang adalah tidak sah dan hanya boleh diakses melalui strim. Fail berada di bawah resources publicvoidtest(){Listnames=newArrayList();InputStreamReaderread=null;try{ClassPathResourceresource=newClassPathResource("name.txt");Input

    Bagaimana SpringBoot menyesuaikan Redis untuk melaksanakan penyirian cache Bagaimana SpringBoot menyesuaikan Redis untuk melaksanakan penyirian cache Jun 03, 2023 am 11:32 AM

    1. Sesuaikan RedisTemplate1.1, mekanisme siri lalai RedisAPI Pelaksanaan cache Redis berasaskan API menggunakan templat RedisTemplate untuk operasi cache data Di sini, buka kelas RedisTemplate dan lihat maklumat kod sumber kelas tersebut. Isytihar kunci, Pelbagai kaedah pesirilan nilai, nilai awal kosong @NullableprivateRedisSe

    Bagaimana untuk melaksanakan Springboot+Mybatis-plus tanpa menggunakan pernyataan SQL untuk menambah berbilang jadual Bagaimana untuk melaksanakan Springboot+Mybatis-plus tanpa menggunakan pernyataan SQL untuk menambah berbilang jadual Jun 02, 2023 am 11:07 AM

    Apabila Springboot+Mybatis-plus tidak menggunakan pernyataan SQL untuk melaksanakan operasi penambahan berbilang jadual, masalah yang saya hadapi akan terurai dengan mensimulasikan pemikiran dalam persekitaran ujian: Cipta objek BrandDTO dengan parameter untuk mensimulasikan parameter yang dihantar ke latar belakang bahawa adalah amat sukar untuk melaksanakan operasi berbilang jadual dalam Mybatis-plus Jika anda tidak menggunakan alatan seperti Mybatis-plus-join, anda hanya boleh mengkonfigurasi fail Mapper.xml yang sepadan dan mengkonfigurasi ResultMap yang berbau dan kemudian. tulis pernyataan sql yang sepadan Walaupun kaedah ini kelihatan menyusahkan, ia sangat fleksibel dan membolehkan kita

    See all articles