这一篇文章,可以把Java中的类加载器了解的七七八八了

ClassFinal实战:3分钟搞定SpringBoot项目JAR包加密(附常见报错解决方案) 本文详细介绍了使用ClassFinal工具对SpringBoot项目JAR包进行加密保护的实战指南。通过三步快速上手、核心命令解析和进阶配置,帮助开发者无需修改源码即可实现代码混淆与防反编译。文章还提供了机器码绑定、依赖加密等高级功能,并附带了常见启动报错与类加载问题的深度排查解决方案,确保加密后的应用稳定运行。 阅读详情

前言

对于每个开发人员来说,java.lang.ClassNotFoundExcetpion这个异常几乎都遇到过,而追求其该异常的来源的话,就免不了谈一谈Java的类加载器了。本文就基于启动类加载器、扩展类加载器、系统类加载器和自定义类加载器来为大家补充一下这方面的知识。

类加载器简介

Java程序被编译器编译之后成为字节码文件(.class文件),当程序需要某个类时,虚拟机便会将对应的class文件进行加载,创建出对应的Class对象。而这个将class文件加载到虚拟机内存的过程,便是类加载。

类加载器负责在运行时将Java类动态加载到JVM(Java虚拟机),是JRE(Java运行时环境)的一部分。由于类加载器的存在,JVM无需了解底层文件或文件系统即可运行Java程序。

Java类不会一次全部加载到内存中,而是在应用程序需要时才会加载。此时,类加载器负责将类加载到内存中。

类加载的过程

类的生命周期通常包括:加载、链接、初始化、使用和卸载。上图中包含了类加载的三个阶段:加载阶段、链接阶段和初始化阶段。如果将这三个阶段再拆分细化包括:加载、验证、准备、解析和初始化。

关于这几个阶段的作用,已经有很多文章在写了,我们就简单概况一下:

  • 加载:通过一个类的完全限定查找类字节码文件,转化为方法区运行时的数据结构,创建一个代表该类的Class对象。
  • 验证:确保Class文件的字节流中包含信息符合当前虚拟机要求,不会危害虚拟机自身安全。
  • 准备:为类变量(即static修饰的字段变量)分配内存并且设置该类变量的初始值。不包含被final修饰的static变量,因为它在编译时已经分配了。
  • 解析:将常量池内的符号引用转换为直接引用的过程。如果符号引用指向一个未被加载的类,或者未被加载类的字段或方法,那么解析将触发这个类的加载。
  • 初始化:类加载最后阶段,若该类具有超类,则对其进行初始化,执行静态初始化器和静态初始化成员变量。

在上述类加载的过程中,虚拟机内部提供了三种类加载器:启动(Bootstrap)类加载器、扩展(Extension)类加载器、系统(System)类加载器(也称应用类加载器)。

下面就讨论不同类型的内置类加载器是如何工作,以及介绍如何自定义类加载器。

内置类加载器

先从一个简单的例子来看一下如何使用不同的加载器来加载不同的类:

public void printClassLoaders() {

    System.out.println("Classloader of this class:"
        + PrintClassLoader.class.getClassLoader());

    System.out.println("Classloader of Logging:"
        + Logging.class.getClassLoader());

    System.out.println("Classloader of ArrayList:"
        + ArrayList.class.getClassLoader());
}

执行上述程序,打印如下内容:

Classloader of this class:sun.misc.Launcher$AppClassLoader@18b4aac2
Classloader of Logging:sun.misc.Launcher$ExtClassLoader@2f0e140b
Classloader of ArrayList:null

上述三行输出分别对应三种不同的类加载器:系统(System)类加载器、扩展(Extension)类加载器和启动(Bootstrap)类加载器(显示为null)。

系统程序类加载器加载包含示例方法的类,也就是将我们自己的文件加载到类路径中。扩展类加载器加载Logging类,也就是加载作为标准核心Java类扩展的类。启动类加载器加载ArrayList类,是所有其他类的父级。

对于ArrayList的类加载器,输出为null。这是因为启动类加载器是用本机代码实现而不是Java,因此它不会显示为Java类。启动类加载器在操作在不同的JVM中会有所不同。

上述三种类加载器,外加自定义类加载器,它们直接的关系可用下图表示:

现在来具体看一下这些类加载器。

Bootstrap类加载器

Java类由java.lang.ClassLoader的实例加载。但是,类加载器本身就是类。那么,谁来加载java.lang.ClassLoader?对,就是启动类加载器。

启动类加载器主要负责加载JDK内部类,通常是rt.jar和$JAVA_HOME/jre/lib目录中的其他核心库。此外,Bootstrap类加载器还充当所有其他ClassLoader实例的父类。

该启动程序类加载器是Java虚拟机的一部分,用本机代码编写(比如,C++),不同的平台的实现可能有所不同。

出于安全考虑,Bootstrap启动类加载器只加载包名为java、javax、sun等开头的类。

Extension类加载器

扩展类加载器是启动类加载器的子类,Java语言编写,由sun.misc.Launcher$ExtClassLoader实现,父类加载器为启动类加载器,负责加载标准核心Java类的扩展。

扩展类加载器从JDK扩展目录(通常是$JAVA_HOME/lib/ext目录)或java.ext.dirs系统属性中指定的任何其他目录进行自动加载。

系统类加载器

系统类加载器负责将所有应用程序级类加载到JVM中。它加载在类路径环境变量,-classpath或-cp命令行选项中找到的文件。它是扩展类加载器的子类。

系统类加载器,也称应用程序加载器是指 Sun公司实现的sun.misc.Launcher$AppClassLoader,负责加载系统类路径-classpath或-D java.class.path指定路径下的类库,也就是我们经常用到的classpath路径,开发者可以直接使用系统类加载器,一般情况下该类加载是程序中默认的类加载器,通过ClassLoader#getSystemClassLoader()方法可以获取到该类加载器。

类加载器是如何工作的

类加载器是Java运行时环境的一部分。当JVM请求一个类时,类加载器将尝试定位该类,并使用完全限定名将类定义装入运行时。

java.lang.ClassLoader.loadClass()方法负责将类定义加载到运行时,它尝试通过全限定名来加载类。如果未加载到该类,则它将请求委派给父类加载器。依次向上重复该过程。

最终,如果父类加载器找不到指定类,则子类将调用java.net.URLClassLoader.findClass()方法在文件系统本身中查找类。

如果最后一个子类加载器也无法加载该类,则它将抛出java.lang.NoClassDefFoundError或java.lang.ClassNotFoundException。抛出ClassNotFoundException时的输出示例:

java.lang.ClassNotFoundException: com.baeldung.classloader.SampleClassLoader    
    at java.net.URLClassLoader.findClass(URLClassLoader.java:381)    
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)    
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)    
    at java.lang.Class.forName0(Native Method)    
    at java.lang.Class.forName(Class.java:348)

上述过程,通常我们称作双亲委派机制。双亲委派机制要求除了顶层的启动类加载器外,其余的类加载器都应当有自己的父类加载器,请注意双亲委派机制中的父子关系并非通常所说的类继承关系,而是采用组合关系来复用父类加载器的相关代码。

除外,类加载器还具有三个重要功能:委派模型、类的唯一性和可见性。

委派模型

类加载器遵循委派模型,在该模型中,根据请求查找类或资源,ClassLoader实例会将对类或资源的搜索委托给父类加载器。

假设我们有一个将应用程序类加载到JVM中的请求。系统类加载器首先将该类的加载委托给其父扩展类加载器,而父扩展类加载器又将其委托给引导类加载器。

仅当启动类加载器和扩展类加载器都未能成功加载类时,系统类加载器才会尝试加载类本身。

类的唯一性

作为委托模型的结果,很容易确保类的唯一性,因为始终尝试向上委托。如果父类加载器无法找到该类,则只有当前实例自己会尝试进行查找和加载。

可见性

此外,子类加载器对其父类加载器加载的类可见。例如,系统类加载器加载的类对扩展和Bootstrap类加载器加载的类具有可见性,反之亦然。

比如,通过系统类加载器加载类A,而通过扩展类加载器加载类B,则对系统类加载器加载的其他类而言,A和B类都是可见的。但对扩展类加载器加载的其他类而言,类B是唯一可见的类。

自定义类加载器

在大多数情况下,如果文件已经在文件系统中,则内置的类加载器就足够了。但是,在需要从本地硬盘驱动器或网络中加载类的情况下,可能需要使用自定义类加载器。下面介绍自定义类加载器的使用。

自定义类加载器示例

自定义类加载器不仅对在运行时加载类有帮助,还有一些特殊的场景:

  • 帮助修改现有的字节码,例如weaving agents;
  • 动态创建适合用户需求的类。例如在JDBC中,通过动态类加载完成不同驱动程序实现之间的切换。
  • 在为具有相同名称和程序包的类加载不同的字节码时,实现类版本控制机制。这可以通过URL类加载器(通过URL加载jar)或自定义类加载器来完成。

举一个更具体的例子,比如,浏览器使用自定义类加载器从网站加载可执行内容。浏览器可以使用单独的类加载器从不同的网页加载applet。用于运行applet的applet查看器包含一个ClassLoader,该类加载器可访问远程服务器上的网站,而无需查看本地文件系统。

然后通过HTTP加载原始字节码文件,并将其转换为JVM中的类。即使这些applet具有相同的名称,但如果由不同的类加载器加载,它们也被视为不同的组件。

现在,我们了解了为什么自定义类加载器是相关的,让我们实现ClassLoader的子类来扩展和总结JVM如何加载类的。

创建自定义类加载器

自定义类加载器通常通过继承java.lang.ClassLoader类,重写findClass()方法:

public class CustomClassLoader extends ClassLoader {

    @Override
    public Class findClass(String name) throws ClassNotFoundException {
        byte[] b = loadClassFromFile(name);
        return defineClass(name, b, 0, b.length);
    }

    private byte[] loadClassFromFile(String fileName)  {
        InputStream inputStream = getClass().getClassLoader().getResourceAsStream(
                fileName.replace('.', File.separatorChar) + ".class");
        byte[] buffer;
        ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
        int nextValue = 0;
        try {
            while ( (nextValue = inputStream.read()) != -1 ) {
                byteStream.write(nextValue);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        buffer = byteStream.toByteArray();
        return buffer;
    }
}

在上面的示例中,我们定义了一个自定义类加载器,该类加载器扩展了默认类加载器并从指定文件加载字节数组。如果没有太复杂的需求,可以直接继承URLClassLoader类,重写loadClass方法,具体可参考AppClassLoader和ExtClassLoader。

了解java.lang.ClassLoader

下面来看看java.lang.ClassLoader类中的一些基本方法,以更清楚地了解其工作方式。

loadClass方法

public Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {

此方法负责加载给定名称参数的类。name参数为类的全限定名。

Java虚拟机调用loadClass()方法来解析类引用,并将resolve设置为true。但是,不一定总是要解析一个类。如果只需要确定该类是否存在,则将resolve参数设置为false。

此方法用作类加载器的入口。我们可以尝试从java.lang.ClassLoader的源代码中了解loadClass()方法的内部工作:

protected Class<?> loadClass(String name, boolean resolve)
  throws ClassNotFoundException {
    
    synchronized (getClassLoadingLock(name)) {
        // First, check if the class has already been loaded
        Class<?> c = findLoadedClass(name);
        if (c == null) {
            long t0 = System.nanoTime();
                try {
                    if (parent != null) {
                        c = parent.loadClass(name, false);
                    } else {
                        c = findBootstrapClassOrNull(name);
                    }
                } catch (ClassNotFoundException e) {
                    // ClassNotFoundException thrown if class not found
                    // from the non-null parent class loader
                }

                if (c == null) {
                    // If still not found, then invoke findClass in order
                    // to find the class.
                    c = findClass(name);
                }
            }
            if (resolve) {
                resolveClass(c);
            }
            return c;
        }
    }

该方法的默认实现按以下顺序搜索类:

  • 调用findLoadedClass(String)方法以查看是否已加载该类。
  • 在父类加载器上调用loadClass(String)方法。
  • 调用findClass(String)方法以查找类。

defineClass方法

protected final Class<?> defineClass(
  String name, byte[] b, int off, int len) throws ClassFormatError

此方法负责将字节数组转换为类的实例。如果数据不包含有效的类,则会抛出ClassFormatError。另外,由于此方法被标记为final,因此我们无法覆盖此方法。

findClass方法

protected Class<?> findClass(
  String name) throws ClassNotFoundException

此方法查找以标准名称作为参数的类。我们需要在遵循委派模型加载类的自定义类加载器实现中重写此方法。

另外,如果父类加载器找不到请求的类,则loadClass()会调用此方法。如果没有任何类加载器的父类找到该类,则默认实现会抛出ClassNotFoundException异常。

getParent方法

public final ClassLoader getParent()

此方法返回父类加载器以进行委派。某些实现使用null来表示启动类加载器。

getResource方法

public URL getResource(String name)

此方法尝试查找具有给定名称的资源。它将首先委托给资源的父类加载器,如果父级为null,则搜索虚拟机内置的类加载器的路径。如果失败,则该方法将调用findResource(String)来查找资源。

指定为输入的资源名称可以相对于类路径,也可以是相对于绝对路径。

它返回用于读取资源的URL对象;如果找不到资源或调用者没有足够的特权来返回资源,则返回null。

需要注意的是,Java是从类路径中加载资源。

最后,Java中的资源加载被认为是与位置无关的,因为只要设置了环境来查找资源,代码在何处运行都无关紧要。

上下文类加载器

通常,上下文类加载器为J2SE中引入的类加载委托方案提供了一种替代方法。JVM中的类加载器遵循分层模型,因此每个类加载器都有一个单独的父类,而启动类加载器除外。但是,有时当JVM核心类需要动态加载应用程序开发人员提供的类或资源时,可能会遇到问题。

例如,在JNDI中,核心功能由rt.jar中的引导程序类实现。但是这些JNDI类可能会加载由独立供应商实现的JNDI提供程序(部署在应用程序类路径中)。这种情况要求启动类加载器(父类加载器)加载对应程序加载器(子类加载器)可见的类。

线程上下文类加载器(context class loader)是从JDK 1.2开始引入的。Java.lang.Thread中的方法 getContextClassLoader()和setContextClassLoader(ClassLoader cl)用来获取和设置线程的上下文类加载器。如果没有通过setContextClassLoader(ClassLoader cl)方法进行设置的话,线程将继承其父线程的上下文类加载器。Java应用运行的初始线程的上下文类加载器是系统类加载器,在线程中运行的代码可以通过此类加载器来加载类和资源。

线程上下文类加载器从根本解决了一般应用不能违背双亲委派模式的问题,使得java类加载体系显得更灵活。上面所提到的问题正是线程上下文类加载器的拿手好菜。如果不做任何的设置,Java应用的线程上下文类加载器默认就是系统类加载器。因此,在SPI接口的代码中使用线程上下文类加载器,就可以成功的加载到SPI实现的类。

小结

类加载器对于执行Java程序是必不可少的。我们先学习了不同类型的类加载器,即Bootstrap类加载器、扩展类加载器和系统类加载器。Bootstrap类加载器充当所有类加载器的父级,负责加载JDK内部类。扩展类加载器和系统类加载器分别从Java扩展目录和类路径加载类。然后,我们学习了类加载器的工作原理、特性,以及如何创建自定义类加载器。

报错:java.lang.ClassNotFoundException: com.mysql.cj.jdbc.Driver at java.base/jdk.internal.loader.Bui 出现了这个问题,是jar包没有导进去。java.lang.ClassNotFoundException: com.mysql.cj.jdbc.Driver at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641) at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders. 阅读详情

相关推荐

霍尔安装歪了也能用?揭秘无感FOC中的‘霍尔自学习’黑科技,实现信号线自适应

本文揭秘了无感FOC中的‘霍尔自学习’黑科技,即使霍尔安装歪了或信号线接错,电机仍能平稳运转。该技术通过算法创新解决了传统霍尔方案的安装公差、接线容错和校准成本问题,显著提升了电机控制的可靠性和效率。文章详细解析了自学习算法的实现架构、关键技术及工程实践中的优化方案,展示了其在工业应用中的卓越性能。

weixin_28309571的博客 463

【错误笔记】IO流 - jdk不同版本问题

错误记录 - IO流出现 Error: A JNI error has occurred, please check your installation and try again Exception in thread "main" 源代码 File file = new File("hello.txt"); System.out.println(file.getAbsoluteFile()); File file1 = new File("File\\hello.txt"); System.ou.

weixin_42580709的博客 969

OLED的字模提取(保姆级)---基于PCtoLCD2013

做为一个刚刚开始接触编程不久的白菜,这个OLED想做一个信息显示,可是商家给我的例程里就是88,816两种字体的格式,我的屏幕是0.91寸的8*16的字体显示上感觉特别丢丢儿小,我就想整个大的,哎,只怪直接学习习惯不好,总是学一半,绕了好大一圈,才搞好,想写一篇博客,时刻提醒踏实学习,第一次写博客,小白一枚,勿喷。。 OLED屏幕驱动程序功能 我们对Markdown编辑器进行了一些功能拓展与语法支...

qq_44886611的博客 7781

通过这一篇文章,可以把Java中的类加载器了解的七七八八了

对于每个开发人员来说,java.lang.ClassNotFoundExcetpion这个异常几乎都遇到过,而追求其该异常的来源的话,就免不了谈一谈Java的类加载器了。本文就基于启动类加载器、扩展类加载器、系统类加载器和自定义类加载器来为大家补充一下这方面的知识。 类加载器简介 Java程序被编译器编译之后成为字节码文件(.class文件),当程序需要某个类时,虚拟机便会将对应的class文件进行加载,创建出对应的Class对象。而这个将class文件加载到虚拟机内存的过程,便是类加载。 类加载器负责在

程序新视界 1308

Ubuntu22.04中通过conda快速部署PyTorch开发环境(CPU/GPU双版本实战)

本文详细介绍了在Ubuntu22.04系统中,如何利用Conda高效部署PyTorch开发环境。文章分别提供了CPU与GPU双版本的实战教程,涵盖环境创建、镜像加速、版本匹配及深度验证等关键步骤,旨在帮助开发者快速搭建稳定、兼容的深度学习环境,从而专注于模型开发。

rose2的博客 556

华为OD机试 - 进制转换 - 二进制(Python/JS/C/C++ 2024 B卷 100分)

华为OD机试 2024E卷题库疯狂收录中,刷题。

学Java,找哪吒 917

Springboot项目打jar包部署访问报错-----ClassNotFoundException: javax.xml.bind.DatatypeConverter

1.访问项目的接口报错,输出如下:(报错的一部分有这个就够了) java.lang.ClassNotFoundException: javax.xml.bind.DatatypeConverter at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:471) ~[na:na] at java.base/java.lang.ClassLoader.loadClass(ClassLoader.j

专注知识分享,希望可以帮助到需要的同行,感谢关注与支持!专注知识分享,希望可以帮助到需要的同行,感谢关注与支持! 975

用 DCL 编写 DEFINE ROLE:把 ABAP CDS 的访问控制做对、做实、做漂亮

摘要: 本文详细讲解如何在ABAP CDS中使用DCL(数据控制语言)实现行级授权,确保业务数据安全。核心要点包括: DCL原理:通过DEFINE ROLE将访问条件绑定到CDS实体,自动附加到查询条件(类似隐式WHERE),保障授权一致性。 关键语法: 必需注解@MappingRole: true声明映射角色。 ASPECT pfcg_auth关联PFCG权限对象,动态控制访问。 注解@AccessControl.authorizationCheck定义授权检查策略(如#CHECK启用强制控制)。 优先级

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 166

出现java.lang.SecurityException:异常处理方法

C:\Users\Admin\.jdks\openjdk-16.0.2\bin\java.exe "-javaagent:D:\IntelliJ IDEA 2021.1.3\lib\idea_rt.jar=51019:D:\IntelliJ IDEA 2021.1.3\bin" -Dfile.encoding=UTF-8 -classpath E:\project\out\production\test java.test01.Dog1 Error: A JNI error has occurred, pl

weixin_42474086的博客 1万+

家用扫地机器人研发技术路线-第四部分:如何一步步做出来 | 4阶段 · 从原型到量产

摘要:本文详细介绍了扫地机器人从原型到量产的研发流程,分为4个关键阶段。首先聚焦四大技术难点:SLAM定位、AI视觉识别、仿生机械臂和静音风机系统。研发过程包括实验室原型验证、工程样机测试、小批量真实场景测试和量产导入四个阶段,每个阶段设有严格评审标准。特别强调测试贯穿全程,包括模块单元测试、整机集成测试、长期可靠性测试和多样化场景模拟,确保产品在上市前完成数百次真实环境验证。整个流程体现了从技术攻关到产品落地的系统性工程思维。

智能硬件研发,欢迎交流 191

全志F1C200S嵌入式驱动开发(lcd屏幕驱动)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】 lcd RGB屏幕作为比较经济、实用的显示工具,在实际场景中使用较多。它的信号来说,一般也比较简单,除了常规的数据信号,剩下来就是行同步、场同步、数据使能和时钟信号了。数据信号方面,常见的格式有RGB888、RGB666、RGB565。为什么有什么多选择,主要还是取决于soc pin脚的多少来定。当然,pin脚越多,显示的颜色就越精准,还原度就越高。 举例来说,假设

嵌入式-老费,一个分享专业嵌入式知识的blog 2794

小豪爱上JVM--类加载机制

小豪最近又收到Java后端开发岗位的面试通知了,数次的失败并没有让小豪丧失斗志,反而在不断的跌倒、站起来的过程中越来越强,像个打不死的小强。为了保险起见,小豪准备让宇哥给自己来一次模拟面试。 故事人物背景介绍 小豪: 23岁,武汉某双非本科不知名专业大学四年级学生,成绩一般,面临毕业,对后端开发、Java很感兴趣,正求职找工作。 宇哥: 跟小豪通过租房认识,两人是室友,26岁,毕业后长期从事软件...

learnjiawa的博客 522

基于STM32设计的掌上游戏机(运行NES游戏模拟器)详细开发过程

利用STM32单片机移植NES游戏模拟器,完成NES游戏开发,可以玩标准的NES游戏,已测试超级玛丽、魂斗罗之类的都可以正常运行。

4万+

2024金三银四快手(Java岗)面经分享

毕竟工作也这么久了 ,除了途虎一轮,也七七八八面试了不少大厂,像阿里、饿了么、美团、滴滴这些面试过程就不一一写在这篇文章上了。我会整理一份详细的面试过程及大家想知道的一些问题细节。

2401_84692226的博客 881

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

java基础面试题大全带答案,1-3年Java开发工程师面试经验分享

毕竟工作也这么久了 ,除了途虎一轮,也七七八八面试了不少大厂,像阿里、饿了么、美团、滴滴这些面试过程就不一一写在这篇文章上了。我会整理一份详细的面试过程及大家想知道的一些问题细节。

2401_84415615的博客 1081

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

为什么你写的 java.lang.String 永远替换不掉?类加载机制深度剖析

类加载机制是 JVM 运行时的基石,而双亲委派模型则是确保核心类安全与一致性的关键设计。很多开发者尝试自定义 java.lang.String,却在编译或运行阶段被拦截,背后涉及 ClassLoader、类文件解析校验以及 JVM 安全边界的多重防护。从一次 loadClass 请求的完整旅行,到 SecurityException 的触发源头,再到 Tomcat 打破双亲委派的实际案例,本文用工程实验还原整个链路,帮助读者理解核心类为何不可篡改。无论你是准备面试、排查类加载异常,还是想深入了解 JVM 设

weixin_29210727的博客 244

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

Android面试速查手册:Java基础篇(1)

毕竟工作也这么久了 ,除了途虎一轮,也七七八八面试了不少大厂,像阿里、饿了么、美团、滴滴这些面试过程就不一一写在这篇文章上了。我会整理一份详细的面试过程及大家想知道的一些问题细节。

2401_84689238的博客 1188

【深夜思考】字节跳动Java三面凉凉,万字长文!

谈起MyBatis,我先提个问:什么是 MyBatis ? MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的持久层框架。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以对配置和原生Map使用简单的 XML 或注解,将接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录… 而今天咱要聊的就是Alibaba珍藏版mybatis手写文档,刷到的朋友真香警告呀! 拼多多二面:多

m0_56301848的博客 313

程序员去大公司面试,java分布式面试题

前言 今天这篇文章中简单介绍一下一个 Java 程序员必知的 Linux 的一些概念以及常见命令。 如果文章有任何需要改善和完善的地方,欢迎在评论区指出,共同进步!笔芯! 正式开始 Linux 之前,简单花一点点篇幅科普一下操作系统相关的内容。 蚂蚁金服关于spring部分面试问题: Spring bean的生命周期能不能结合源码回答一下这个问题 Spring容器当中包含了哪些常用组件(至少说5个),作用是什么,场景是什么; Spring自动注入的原理是什么?能不能从源码来说明一下这个问题; 我们常常说

m0_57983503的博客 162

2024年京东、拼多多、腾讯,BAT大厂面试总结

毕竟工作也这么久了 ,除了途虎一轮,也七七八八面试了不少大厂,像阿里、饿了么、美团、滴滴这些面试过程就不一一写在这篇文章上了。我会整理一份详细的面试过程及大家想知道的一些问题细节。

2401_83621004的博客 465

物联网工控机选型:Java与.NET在内存、启动与部署上的实战对比

物联网边缘层常部署在资源受限的工控机上,内存占用与启动性能直接决定系统稳定性。Java依托JVM生态虽成熟,但默认占用高、启动慢,在老旧设备上易引发“是否需要换机器”的尴尬;而.NET Core通过紧凑运行时与Native AOT发布,能将内存降至百兆级、启动压缩至秒内,并实现单文件免依赖部署。结合MQTT轻量通信与SQLite嵌入式存储,可显著降低边缘节点资源压力,提升断电恢复速度,为产线数据采集提供高性价比方案。本文以真实项目对比数据为例,梳理Java与.NET在物联网边缘场景的底层差异、重写优化要点及

weixin_29165725的博客 77

Java OOM 排查实战:从报错类型到根因定位的完整方法论

JVM 内存管理是 Java 后端开发的核心基础,理解堆、元空间、直接内存等运行时数据区的分配与回收机制,是保障服务稳定性的关键。当 JVM 内存区域耗尽时,会抛出 OutOfMemoryError,但不同区域溢出对应的排查路径截然不同。掌握 jstat、jmap、jstack 等命令行工具与 MAT 等分析工具的组合使用,能够快速定位内存泄漏、流量突刺或配置不当等根因。在生产环境中,合理配置 GC 日志与 OOM 自动 dump 是高效排查的前提。本文围绕 Java OOM 原因以及问题分析排查步骤,系统

weixin_34023982的博客 294

大厂必备,转疯了

谈起MyBatis,我先提个问:什么是 MyBatis ? MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的持久层框架。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以对配置和原生Map使用简单的 XML 或注解,将接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录… 而今天咱要聊的就是Alibaba珍藏版mybatis手写文档,刷到的朋友真香警告呀! 拼多多二面:多

EDGNB123的博客 249

MySQL千万数据量深分页优化,成功拿到offer

02 JVM 线程 JVM内存区域 JVM运行时内存 垃圾回收与算法 JAVA四种引用类型 GC分代收集算法 VS 分区收集算法 GC垃圾收集器 JAVA IO/NIO JVM类加载器 03 JAVA集合 接口继承关系和实现 LIST SET MAP 04 JAVA多线程并发 JAVA并发知识库 JAVA线程实现/创建方式 4种线程池 线程生命周期(状态) 终止线程4种方式 sleep与wait区别 start与run区别 JAVA后台线程 JAVA锁 线程基本方法 线程上下文切换 同步锁与死

m0_57472099的博客 217

GitHub上标星77

毕竟工作也这么久了 ,除了途虎一轮,也七七八八面试了不少大厂,像阿里、饿了么、美团、滴滴这些面试过程就不一一写在这篇文章上了。我会整理一份详细的面试过程及大家想知道的一些问题细节。

ghfgjfg679的博客 742

xjar加密jar包部署Linux全流程:原理、实操与避坑指南

在Java后端私有化交付中,jar包加密是保护核心代码与敏感配置的关键手段。其原理是通过自定义类加载器在运行时解密并加载加密字节码,从而提升反编译门槛。xjar作为字节码加密方案,以低侵入性和高兼容性著称,尤其适合Spring Boot项目。它能在不修改业务代码的前提下,对class文件及yml、properties等配置文件进行AES加密,有效防止源码泄露和授权绕过。部署到Linux服务器时,需关注密码安全传递、类加载冲突及配置文件读取等工程实践问题。本文围绕xjar的加密原理、命令行与Maven插件实操

weixin_32288959的博客 205
上一篇: JavaSE-09 Thread 多线程
下一篇: 排查问题的技巧:索引,GC,容器,网络抓包,全链路追踪等技能
JavaShark
博客等级 码龄4年 184粉丝 438原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值