JVM三大子系统之类加载子系统(二)

2023-11-18

前置说明:由于个人能力有限,下面文章会大量整理、引用其他人的文章,我个人主要把这篇文章当成是自己的学习笔记

通过前面的文章,我们知道了,一段java代码是如何运行的?
1、【编译】程序员编写的java文件(编译成)class文件
2、【加载】JVM通过类加载器进行加载该class文件
3、【解释】class文件(通过JVM的执行引擎翻译成)机器码
4、【执行指令】机器码(通过特定平台的操作系统)运行在这里插入图片描述
接下来我们要讲的就是其中的第二步:类加载子系统
类加载:JVM通过类加载器进行加载class文件
首先,我们需要了解下class文件

一、Class文件

1、class文件的二进制形式(了解即可)

JVM—加载到方法区的Class文件长什么样?——在这篇文章你可看见class文件的二进制形式
在这里插入图片描述
【推荐阅读】:Java虚拟机:class类文件结构

class类文件的结构:

  1. 魔数
  2. 文件版本信息
  3. 常量池
  4. 访问标志
  5. 类索引、父类索引、接口索引集合
  6. 字段表集合
  7. 方法表集合
  8. 属性表集合

2、使用javap工具反汇编查看class文件

【推荐阅读】java常用工具
正常来说,我们不会直接看这种二进制,我们可以使用javap工具帮助阅读
javap -c +class文件(在class文件所在的目录下或者写class文件的全路径)
-c 对代码进行反汇编
-p 将打印私有的字段和方法;
-v 即verbose 输出附加信息

如何使用javap工具?
1、使用javac xxxx.java // 编译出class文件
2、使用javap -c -p -v +class文件 //反汇编查看class文件

java原文件

public class test003_helloworld {
    final private String name ="张三";
    public static void main(String[] args) {
        int a =1;
        int b =2;
        int c;
        c =a+b;
        System.out.println(c);
        System.out.println("hello world");
        System.out.println("hello world2");
    }}

反汇编后的内容:

Classfile /D:/IDEAProjects/000Users/ZKF/HomeWork/src/com/zkf/JVM/003Heap/test003_helloworld.class
  Last modified 2022930; size 566 bytes
  SHA-256 checksum c8bbe0b4ff6cbdff4e3090a13a95cc0501e7a1af28d32ad07538d57a84d0cc14
  Compiled from "test003_helloworld.java"
public class test003_helloworld
  minor version: 0
  major version: 59
  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
  this_class: #10                         // test003_helloworld
  super_class: #2                         // java/lang/Object
  interfaces: 0, fields: 1, methods: 2, attributes: 1
Constant pool:
   #1 = Methodref          #2.#3          // java/lang/Object."<init>":()V
   #2 = Class              #4             // java/lang/Object
   #3 = NameAndType        #5:#6          // "<init>":()V
   #4 = Utf8               java/lang/Object
   #5 = Utf8               <init>
   #6 = Utf8               ()V
   #7 = String             #8             // 寮犱笁
   #8 = Utf8               寮犱笁
   #9 = Fieldref           #10.#11        // test003_helloworld.name:Ljava/lang/String;
  #10 = Class              #12            // test003_helloworld
  #11 = NameAndType        #13:#14        // name:Ljava/lang/String;
  #12 = Utf8               test003_helloworld
  #13 = Utf8               name
  #14 = Utf8               Ljava/lang/String;
  #15 = Fieldref           #16.#17        // java/lang/System.out:Ljava/io/PrintStream;
  #16 = Class              #18            // java/lang/System
  #17 = NameAndType        #19:#20        // out:Ljava/io/PrintStream;
  #18 = Utf8               java/lang/System
  #19 = Utf8               out
  #20 = Utf8               Ljava/io/PrintStream;
  #21 = String             #22            // hello world
  #22 = Utf8               hello world
  #23 = Methodref          #24.#25        // java/io/PrintStream.println:(Ljava/lang/String;)V
  #24 = Class              #26            // java/io/PrintStream
  #25 = NameAndType        #27:#28        // println:(Ljava/lang/String;)V
  #26 = Utf8               java/io/PrintStream
  #27 = Utf8               println
  #28 = Utf8               (Ljava/lang/String;)V
  #29 = String             #30            // hello world2
  #30 = Utf8               hello world2
  #31 = Utf8               ConstantValue
  #32 = Utf8               Code
  #33 = Utf8               LineNumberTable
  #34 = Utf8               main
  #35 = Utf8               ([Ljava/lang/String;)V
  #36 = Utf8               SourceFile
  #37 = Utf8               test003_helloworld.java
{
  private final java.lang.String name;
    descriptor: Ljava/lang/String;
    flags: (0x0012) ACC_PRIVATE, ACC_FINAL
    ConstantValue: String 寮犱笁

  public test003_helloworld();
    descriptor: ()V
    flags: (0x0001) ACC_PUBLIC
    Code:
      stack=2, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: aload_0
         5: ldc           #7                  // String 寮犱笁
         7: putfield      #9                  // Field name:Ljava/lang/String;
        10: return
      LineNumberTable:
        line 1: 0
        line 2: 4

  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
    Code:
        stack=2, locals=4, args_size=1
         0: iconst_1
         1: istore_1
         2: iconst_2
         3: istore_2
         4: iload_1
         5: iload_2
         6: iadd
         7: istore_3
         8: getstatic     #15                 // Field java/lang/System.out:Ljava/io/PrintStream;
        11: iload_3
        12: invokevirtual #21                 // Method java/io/PrintStream.println:(I)V
        15: getstatic     #15                 // Field java/lang/System.out:Ljava/io/PrintStream;
        18: ldc           #27                 // String hello world
        20: invokevirtual #29                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        23: getstatic     #15                 // Field java/lang/System.out:Ljava/io/PrintStream;
        26: ldc           #32                 // String hello world2
        28: invokevirtual #29                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        31: return
      LineNumberTable:
        line 5: 0
        line 6: 2
        line 8: 4
        line 9: 8
        line 10: 15
        line 11: 23
        line 12: 31
}
SourceFile: "test003_helloworld.java"

javap返汇编后的内容 一般包括以下四个部分

2.1、基本信息

Classfile /D:/workspace/donkey/cimc-im-desktop/target/classes/com/brilliantstar/cimc/im/desktop/Demo.class
Last modified 2018-9-6; size 909 bytes//上次修改时间、大小909字节

MD5 checksum 0f9cd841c4a2ab1f6a00163e55ca6e0f//MD5算法
Compiled from "Demo.java"//编译自Demo.java文件
public class com.brilliantstar.cimc.im.desktop.Demo
minor version: 0//java小版本
major version: 52//java大版本(52对应jdk8版本)

flags: ACC_PUBLIC, ACC_SUPER//类的修饰符

附:md5是什么:

md5将整个文件当作一个大文本信息,通过其不可逆的字符串变换算法,产生了这个唯一的md5信息摘要。
md5就可以为任何文件(不管其大小、格式、数量)产生一个同样独一无二的“数字指纹”,如果任何人对文件做了任何改动,其md5值也就是对应的“数字指纹”都会发生变化

2.2 常量池(用来存放各种常量及符号引用)

常量池中的每一项都有一个对应的索引(如 #1),并且可能引用其他的常量池项(#1 = Methodref #6.#21)
在这里插入图片描述
Methodref:方法引用 后面两个引用表示【方法所属类】和【调用的方法名】
在这里插入图片描述

Fieldref:表示属性引用 【所属类】和【成员变量名】
NameAndType:
【方法名】: <init>表示构造方法,
【参数类型、返回值类型】: ()V 无参,V表示返回类型Void

描述符:描述方法的参数类型以及返回值类型
如上述例子:<( [ Ljava / lang / String;)V>
说明参数类型是Ljava / lang / String;返回值类型是V,即为 void 类型
同理:其他标识字符如下
在这里插入图片描述

2.3 字段区域,用来列举该类中的各个字段

这里最主要的信息便是该【字段的类型(descriptor: I)】以及【访问权限(flags: (0x0002) ACC_PRIVATE)】
对于声明为 final 的静态字段而言,如果它是基本类型或者字符串类型,那么字段区域还将包括它的常量值
在这里插入图片描述

2.4 方法区域(用来列举该类中的各个方法)

每个方法中包含以下5类信息

  • 1、方法描述符和访问权限
  • 2、每个方法还包括最为重要的代码区域(Code:)
    Code代码区域一开始会声明该方法中的

2.1、操作数栈最大深度stack:2

(操作数栈主要用于:保存计算过程中的中间结果,同时作为计算过程中变量临时的存储空间)
(说明这里为什么是2?a+b 同时操作a+b)
如果是System.out.println(a+b);那么stack为3,因为还要操作一个System.out引用

2.2、局部变量最大槽数locals:4

3定义了abc3个变量 加上0索引位置的this引用
(局部变量表从1开始计数 , 并不是没有第 0个元素 , 第0个元素是当前类 this , 这是所有的局部变量表固定的格式)
注意这里局部变量指的是字节码中的局部变量,而非 Java 程序中的局部变量

2.3、该方法接收参数的个数(args_size=1)

  • 3、方法的字节码
    (每条字节码均标注了对应的偏移量,这是用来定位字节码的)

  • 4、异常表(Exception table:)

  • 5、行数表(LineNumberTable)则是Java源程序到字节码偏移量的映射

附:行数表和局部变量表均属于调试信息。Java 虚拟机并不要求 class 文件必备这些信息

3、推荐jclasslib插件

jclasslib 插件安装及使用
使用这款插件可以很方便的查看class的字节码指令
附图:在这里插入图片描述

二、类加载

部分内容引用:搞懂java类加载机制和类加载器

上面讲完了class文件的结构后,同时,我们知道程序主动使用某个类时,如果该类还未被加载到内存中,则JVM会通过类加载器进行类加载该class文件到内存,完成该类进行初始化
类的生命周期(7个阶段):【加载、连接(验证、准备、解析)、初始化】、使用、卸载
在这里插入图片描述

(验证、准备、解析三个阶段统称为连接)
(类加载的全过程为前面的5个阶段)

1、加载阶段

定义:加载指的是将类的class文件读入到内存,并将这些静态数据转换成方法区中的运行时数据结构,并【在堆中生成一个代表这个类的java.lang.Class对象】,作为方法区类数据的访问入口,【这个过程需要类加载器参与】

加载阶段需要完成3件事:
1、(通过一个类的全限定名来)【获取】定义此【类的二进制字节流】
2、将这个字节流所代表的【静态存储结构转化方法区的运行时数据结构】(将类的字节码载入方法中,内部采用c++的instanceKlass描述java类),它的重要field有:

_java_mirror 即 java 的类镜像,例如对 String 来说,就是 String.class,作用是把 klass 暴露给 java使用
_super 即父类
_fields 即成员变量
_methods 即方法
_constants 即常量池
_class_loader 即类加载器
_vtable 虚方法表
_itable 接口方法表

3、在【堆内存中生成】一个代表这个类的java.lang.Class对象作为方法区这个类的各种数据的访问入口

(该Class对象封装了类在方法区中的数据结构,并且向用户提供了访问方法区数据结构的接口,即Java反射的接口

思考:【java类信息存储在方法区中】,类的对象在堆中,那么对象是如何获取类信息的呢?
1、类在JVM中是用【InstanceKlass】的实例表示,用来描述【保存】【Java类的信息】并存在元空间(metaSpace) /即方法区
2、每个对象的对象头中都保存了指向类的指针,通过该指针找到Class对象的地址(该Class对象保存了_java_mirror的地址,而_java_mirror保存了instanceKlass地址)
在这里插入图片描述
附:深入讲解Java的对象头与对象组成
总结:
1、加载类信息到方法区(元空间)

2、生成Class对象(堆中)

3、目的(堆中有了Class对象后能做什么?):
堆中对象能获取方法区中的类信息

(过程)堆对象–Class对象–(方法区中)instanceKlass ,获取类信息

2、连接阶段

定义:当类被加载之后,系统为之生成一个对应的Class对象,接着将会进入连接阶段,连接阶段负责把类的二进制数据合并到JRE中(意思就是将java类的二进制代码合并到JVM的运行状态之中)类连接又可分为如下3个阶段

2.1、验证:确保加载的类信息符合JVM规范,没有安全方面的问题。主要验证是否符合Class文件格式规范,并且是否能被当前的虚拟机加载处理.

验证阶段大致上分为四个阶段的检验动作:文件格式验证、元数据验证、字节码验证和符号引用验证

2.2、准备:正式为类变量(static变量)分配内存空间并设置类变量初始值(默认值) 的阶段,这些内存都将在方法区中进行分配
备注:类变量不包括实例变量

附加说明:

  1. static变量在JDK7之前存储于instanceKlass末尾,从JDK 7开始,存储于_java_mirror末尾
  2. static变量分配空间和赋值是两个步骤,分配空间在准备阶段完成,【赋值在初始化阶段完成】
  3. 赋值的两个例外:
    如果static变量是final的基本类型(以及字符串常量final static String a= “hello”),那么【编译阶段】值就确定了,赋值在准备阶段完成(final static int a = 20;因为常量必须赋值)
  4. 如果static变量是final的,但属于引用类型,那么赋值也会在初始化阶段完成

2.3、解析:虚拟机常量池的符号引用替换为直接引用过程

符号引用:符号引用以一组符号来描述所引用的目标,符号可以使任何形式的字面量,只要运行时能定位到目标即可

直接引用:
直接引用可以使直接指向目标的指针、相对偏移量或是一个能间接定位到目标的句柄。直接引用和迅疾的内存布局实现有关。
直接引用的目标一定已经加载到了虚拟机的内存中了

(虚拟机可以根据需要自行判断,到底是在类被加载器加载时就对常量池中的符号引用进行解析,还是等到一个符号引用将要被使用前才去解析它)

解析动作主要针对类或接口、字段、类方法、接口方法、方法类型、方法句柄和调用点限定符 7 类符号引用进行,分别对应于常量池的 7 中常量类型

3、初始化

执行类的类构造器<clinit>方法(为变量完成赋值)

(前面的几个类加载的动作,除了在加载阶段用户可以通过自定义类加载器的方式局部参与外,其余动作都完全由java虚拟机来主导控制【直到初始化阶段,Java虚拟机才真正开始执行类中编写的Java程序代码,将主导权移交给应用程序】)

如何判断类进行了初始化?

类的初始化就是执行cinit方法,这个方法是由编译器自动收集类中的所有类变量的赋值动作和静态语句块(static{}块)中的语句【合并产生】的,可以用静态代码块是否执行为依据来判断类是否初始化了

不会导致类初始化的情况

  • 访问类的static final静态常量(基本类型和字符串)不会触发初始化
    (编译阶段)
    备注:statis final Integer c =20;算是final修饰引用类型 ,会触发类的初始化(因为Integer.valueOf(20))
  • 类对象.class不会触发初始化(1、加载阶段)
  • 创建该类的数组不会触发初始化(同上,也是只加载了类)
  • 类加载器的loadClass方法(1、加载阶段)
    Class.forName的参数2为false时(该参数表示不进行类的初始化)

那什么时候进行初始化呢?概括得说,类初始化是【懒惰的】

  • main方法所在的类,总会被首先初始化
  • 首次访问这个类的静态变量或静态方法时
  • 【子类初始化】,如果父类还没初始化, 会引发(因为子类初始化要使用父类的东西)
  • 子类【访问父类的静态变量】,只会触发父类的初始化
  • Class.forName
  • new会导致初始化(执行构造方法)

4、各个阶段的小总结

加载:在堆中生成Class对象,作为方法区类数据的访问入口
验证:验证字节码的文件的正确性(4种验证)文件格式的验证,字节码验证,符号引用的验证
准备:在方法区中为【类变量】分配内存空间并设置类中变量的【初始值】
解析:把类里面引用的其他类也加载进来,把符号引用转变为直接引用,也叫静态链接。
初始化:给静态变量一些真正的值,执行静态代码块。
使用:执行引擎
卸载:异常终止,操作系统错误,程序结束

三、类加载器

【推荐阅读】:JVM–三大子系统详解

1、类加载器是什么?

JVM设计团推有意把“通过一个类的全限定名来获取描述该类的二进制字节流”(加载阶段)这个动作放到JVM外部去实现,以便让应用程序自己决定如何去获取所需的类。实现这个动作的代码被称为“类加载器”(Class Loader)

2、类加载器的分类

启动类加载器(Bootstrap ClassLoader):负责加载java_HOME/lib目录中的类库,启动程序。
扩展类加载器(Extension ClassLoader):负责加载java_HOME/lib/ext目录中的类库,外部库。
应用程序类加载器 (Application ClassLoader):负责加载用户自己写的类库

名称 加载哪些类 说明
Bootstrap ClassLoader JAVA_HOME/jre/lib 无法直接访问
(getClassLoader显示为null)
Extension ClassLoader JAVA_HOME/jre/libl/ext 上级为Bootstrap
(getparent显示为null)
Application ClassLoader classpath 上级为Extension
自定义类加载器 自定义 上级为Application

3、双亲委派模型类加载机制

JVM通过双亲委派机制对类进行加载。双亲委派机制是指一个类在收到类加载的请求后不会尝试自己加载这个类,而是把该类加载请求向上委派给其父类去完成,其父类在接收到该类加载请求后又会将其委派给自己的父类,以此类推,这样所有的类加载请求都被向上委派到启动类加载器中。若父类加载器在接收到类加载请求后发现自己也无法加载该类(通常原因是该类的Class文件在父类的类加载器中不存在),则父类将会将该信息反馈给子类并向下委派子类加载器加载该类,直到该类被加载成功,若是找不到该类,则JVM会抛出ClassNotFoud异常。
具体流程如下所示:在这里插入图片描述原文链接:https://blog.csdn.net/Artisan_w/article/details/105365314

双亲委派模型的好处:双亲委派模式可以保证Java程序的稳定运行,防止重复加载和任意修改

比如java.lang.Object,无论哪个类加载器需要加载这个类,最终都由Bootstrap ClassLoader加载,因此Object在程序的各个类加载器环境都是同一个类。相反,如果如果不用双亲委派模型进行加载,用户自定义了一个Object类并放置在类路径下,最终可能会引发程序混乱

双亲委派模型很好地解决了基础类的统一问题,保证了虚拟机的安全性

双亲委派模型的缺陷:

有些接口是Java核心库提供的,而java核心库是由启动类加载器进行加载,而这些接口的实现却是来自于不同的厂商提供的jar包,java的启动类加载器是不会加载这些jar包,这样传统的双亲委托模式就无法满足SPI的要求。
(SPI机制是JDK提供接口,第三方Jar包实现该接口)

https://zhuanlan.zhihu.com/p/185612299
举例: 接口:java.sql.Driver,定义在java.sql包中,包所在的位置是:jdk\jre\lib\rt.jar中,java.sql包中还提供了其它相应的类和接口比如管理驱动的类:DriverManager类,
很明显java.sql包是由BootstrapClassloader加载器加载的;而接口的实现类com.mysql.jdbc.Driver是由第三方实现的类库,由AppClassLoader加载器进行加载的

问题:【当前类加载器为启动类加载器】,要加载子类的mysql数据库驱动(com.mysql.jdbc.Driver类)【需要的类加载器为:应用类加载器】,这就是由BootstrapClassloader加载的类使用了由AppClassLoader加载的类,很明显和双亲委托机制的原理相悖

上面的问题中,我们需要一个工具,来帮助我们从启动类加载器 改变成 应用类加载器,这个工具就是线程上下文类加载器

如何解决?
类似这种,接口由启动类加载器加载,但是由于实现类由第三方实现,不在JDK中,无法加载实现类,都需要反向委派,由线程上下文加载器加载第三方实现类,【通过当前线程设置上下文类加载器】设置的上下文类加载器来【实现对于接口实现类的加载】

4、线程上下文类加载器

线程上下文加载器之所以打破双亲委派模型是因为:
【双亲委派模型依赖的单一方向的,并不能解决父类加载器去依赖子类加载器这种逆方向需求】,此时,需要线程上下文类加载器修改当前类加载器

如何加载?
1、获取现在类加载器(为了获取线程上下文加载器)
2、获取线程上下文加载器
3、自定义方法

备注:如果没有设置线程上下文类加载器,该加载器默认为应用类加载器

//1、获取现在类加载器(为了获取线程上下文加载器)
//2、获取线程上下文加载器
ClassLoader calssLoader = Thread.currentThread().getContextClassLoader();
 
try {
    //设置线程上下文类加载器为自定义的加载器
    Thread.currentThread.setContextClassLoader(targetTccl);
    myMethod(); //执行自定义的方法
} finally {
    //还原线程上下文类加载器
    Thread.currentThread().setContextClassLoader(classLoader);
}

线程上下文类加载器的适用场景:

  1. 当高层提供了统一接口让低层去实现,同时又要是在高层加载(或实例化)低层的类时,必须通过线程上下文类加载器来帮助高层的ClassLoader找到并加载该类。
  2. 当使用本类托管类加载,然而加载本类的ClassLoader未知时,为了隔离不同的调用者,可以取调用者各自的线程上下文类加载器代为托管。
    引用自:https://www.cnblogs.com/jelly12345/p/15668489.html

简而言之就是ContextClassLoader默认存放了AppClassLoader的引用,由于它是在运行时被放在了线程中,所以不管当前程序处于何处(BootstrapClassLoader或是ExtClassLoader等),在任何需要的时候都可以用Thread.currentThread().getContextClassLoader()取出应用程序类加载器来完成需要的操作

附:启动器类加载器追加路径

可以将自定义的类手动添加到Bootstrap类加载器的范围内

-Xbootclasspath表示设置bootclasspath
/a:.表示将【当前目录】追加至bootclasspath之后
在这里插入图片描述
启动类加载器的核心类可以修改和替换

  • java -Xbootclasspath: //设置新路径
  • java -Xbootclasspath/a:<追加路径> //后追加路径
  • java -Xbootclasspath/p:<追加路径> //前追加路径,一般不用,是给JVM底层开发的人用的
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

JVM三大子系统之类加载子系统(二) 的相关文章

  • 未找到 MessageSource 的 ResourceBundle [消息]:找不到基本名称消息的包

    在 applicationContext xml 中 我定义了 MessageSource 如下所示
  • Android 2.2 SDK - Droid X 相机活动无法正常完成

    我注意到我在 Droid X 上调用的默认相机活动与我的 Droid 和 Nexus One 上的默认相机活动看起来不同 在 Droid 和 Nexus One 上选择 确定 后 活动将完成 Droid X 有一个 完成 按钮 它将带您返回
  • 添加动态数量的监听器(Spring JMS)

    我需要添加多个侦听器 如中所述application properties文件 就像下面这样 InTopics Sample QUT4 Sample T05 Sample T01 Sample JT7 注意 这个数字可以多一些 也可以少一些
  • 如果在睡眠线程上调用interrupt()会发生什么?

    我有一个线程 然后run I call sleep 如果我中断这个线程会发生什么 MyThread extends Thread public void run try sleep 1000000 catch InterruptedExce
  • 无法使用maven编译java项目

    我正在尝试在 java 16 0 1 上使用 maven 构建 IntelliJ 项目 但它无法编译我的项目 尽管 IntelliJ 能够成功完成 在此之前 我使用maven编译了一个java 15项目 但我决定将所有内容更新到16 0 1
  • 如何从秘密字符串中制作 HMAC_SHA256 密钥以在 jose4j 中与 JWT 一起使用?

    我想生成 JWT 并使用 HMAC SHA256 对其进行签名 对于该任务我必须使用jose4j https bitbucket org b c jose4j wiki Home 我尝试根据秘密生成密钥 SecretKeySpec key
  • 来自数据库的 jfreechart 散点图

    如何使用java中的jfreechart绘制mysql数据库表中数据的散点图 我使用过 Swing 库 任何链接都会有帮助 我搜索了谷歌但找不到理解的解决方案 如果您有代码 请提供给我 实际上我确实做了条形图并使用 jfreechart 绘
  • Java:使用 HttpURLConnection 的 HTTP PUT

    如何执行 HTTP PUT 我正在使用的类似乎认为它正在执行 PUT 但端点将其视为我执行了 GET 我做错了什么吗 URL url new URL https HttpURLConnection conn HttpURLConnectio
  • Java套接字:在连接被拒绝异常时重试的最佳方法?

    现在我正在这样做 while true try SocketAddress sockaddr new InetSocketAddress ivDestIP ivDestPort downloadSock new Socket downloa
  • Scala 为了在 JVM 上运行做出了哪些妥协?

    Scala 是一种很棒的语言 但我想知道如果它有自己的运行时 如何改进 IE 由于 JVM 的选择 做出了哪些设计选择 我所知道的两个最重要的妥协是 类型擦除 http java sun com docs books tutorial ja
  • Java:正则表达式排除空值

    在问题中here https stackoverflow com questions 51359056 java regexp for a separated group of digits 我得到了正则表达式来匹配 1 到 99 之间的一
  • 如何将 Jfreechart(饼图)添加到 netbeans 的面板中

    我正在使用 netbeans gui 编辑器 并且正在尝试添加一个本身位于内部框架中的 Jfreechart 并且这个内部框架我想将其添加到面板中 正如您在此图中看到的那样 抱歉 我无法直接发布图像 因为我新手 http www flick
  • 获取给定类文件的目录路径

    我遇到的代码尝试从类本身的 class 文件所在的同一目录中读取一些配置文件 File configFiles new File this getClass getResource getPath listFiles new Filenam
  • Spring Security OAuth2简单配置

    我有一个简单的项目 需要以下简单的配置 我有一个 密码 grant type 这意味着我可以提交用户名 密码 用户在登录表单中输入 并在成功时获得 access token 有了该 access token 我就可以请求 API 并获取用户
  • 哪个集合更适合存储多维数组中的数据?

    我有一个multi dimensional array of string 我愿意将其转换为某种集合类型 以便我可以根据自己的意愿添加 删除和插入元素 在数组中 我无法删除特定位置的元素 我需要这样的集合 我可以在其中删除特定位置的数据 也
  • Java的-XX:+UseMembar参数是什么

    我在各种地方 论坛等 看到这个参数 并且常见的答案是它有助于高并发服务器 尽管如此 我还是找不到 sun 的官方文档来解释它的作用 另外 它是Java 6中添加的还是Java 5中存在的 顺便说一句 许多热点虚拟机参数的好地方是这一页 ht
  • Android - 9 补丁

    我正在尝试使用 9 块图片创建一个新的微调器背景 我尝试了很多方法来获得完美的图像 但都失败了 s Here is my 9 patch 当我用Draw 9 patch模拟时 内容看起来不错 但是带有箭头的部分没有显示 或者当它显示时 这部
  • 在android中跟踪FTP上传数据?

    我有一个运行 Android 的 FTP 系统 但我希望能够在上传时跟踪字节 这样我就可以在上传过程中更新进度条 安卓可以实现这个功能吗 现在 我正在使用org apache common net ftp我正在使用的代码如下 另外 我在 A
  • 嵌入式 Jetty - 以编程方式添加基于表单的身份验证

    有没有一种方法可以按如下方式以编程方式添加基于表单的身份验证 我用的是我自己的LdapLoginModule 最初我使用基本身份验证并且工作正常 但现在我想在登录页面上进行更多控制 例如显示徽标等 有没有好的样品 我正在使用嵌入式 jett
  • JAXB - 列表<可序列化>?

    我使用 xjc 制作了一些课程 public class MyType XmlElementRefs XmlElementRef name MyInnerType type JAXBElement class required false

随机推荐

  • 快速排序 详解(快速排序 双路快排 三路快排)

    注 内容 图片来自于慕课网liuyubobobo老师的课程 官方代码链接 https github com liuyubobobo Play with Algorithms 快速排序 快速排序可以说是20世纪最伟大的算法之一了 相信都有所耳
  • Stm32 一键下载电路详解

    文章目录 前言 一键下载 一键下载原理 硬件原理图 跳帽与启动 存储映射 串口下载程序由来 一键下载流程 通过 USB 控制机器复位握手 解读 前言 最近在又要折腾 stm32 了 所以翻出了角落里的开发板 先复习下怎么一键下载来着 一键下
  • linux中安装mysql时报错解决方案

    转载于http www cnblogs com xiaolang8762400 p 6950920 html 找了很久才找到 谢谢大神 本人需要找的问题主要是安装时出错的解决方法 本人的文件版本跟原创的版本有点不一样 需要哪个版本自行选择
  • 实战:从Mysql数据库frm文件中,提取表结构创建SQL语句

    需求 在某些特殊的场景下 例如你的mysql数据库无法启动 需要你将表的ibd文件拷贝到另一个数据库中 恢复业务数据库 恢复业务数据的前提 是你需要在另一个数据库中 创建好一模一样的表结构 这时你就需要从Mysql数据库的frm文件中 提取
  • Mysql查询日期timestamp格式的数据

    在Navicat中 时间戳 timestamp 格式的数据表现为 查询某一天的数据 SELECT FROM my table WHERE update time LIKE 2022 10 06 或是 SELECT FROM my table
  • 如何成功开展网络营销?

    企业如要将网上营销开展成功 则必须注意以下方面 1 准确 客观的市场定位 网上营销同传统的营销相比 其前期工作也包括准确客观的市场定位 网上营销与一般营销有较大的区别 因此其市场定位也有其独特的特点 如何准确客观地进行网上营销的市场定位 必
  • CentOS8更换阿里源及解决yum update报错问题

    CentOS更换阿里源 yum makecache提示错误 为 repo base 下载元数据失败 Cannot download repomd xml Cannot download repodata repomd xml All mir
  • GitHub的使用

    文章目录 一 通过实际操作学习Git 1 Git基本操作 2 分支操作 3 更改提交操作 4 推送至远程仓库 5 从远程仓库获取 6 帮助大家深入理解Git资料 二 工具栏 1 键盘快捷键 2 工具栏 3 控制面板 4 仓库 三 与GitH
  • vite插件介绍 - vite-plugin-meta-env

    vite插件介绍 vite plugin meta env a vite plugin define dynamic env variables in import meta env npm github 可以基于本仓库去开发自己的vite
  • 微信小程序怎么设置单个页面颜色/顶部栏颜色/tabBar颜色

    微信小程序怎么设置单个页面的背景颜色 这个其实很简单 看看酱茄小编是怎么操作的 在对应的json里面写入以下代码即可 单页页面的背景颜色设置方法 navigationBarBackgroundColor FFFFFF 小程序tabBar 底
  • 数据清洗---数据整合

    数据整合可以使用Pandas库中merge 函数合并数据集 import pandas as pd 建两个数据集 df1 DataFrame lkey b b a c data1 range 4 df2 DataFrame rkey a b
  • 写selenium常用到的js代码

    selenium可以运行JavaScript代码 可以用一些JavaScript来辅助编写Selelnium代码 1 scrollIntoView 向下拉滚动条 使得某元素可见 IWebElement element driver Find
  • tensorflow NameError: name ‘layers‘ is not defined解决办法

    错误代码 import tensorflow as tf net layers Dense 10 net build 4 10 net kernel NameError name layers is not defined 错误原因 ten
  • 如何使用jquery通过id值修改指定的input的value值

    如何使用jquery通过id值修改指定的input的value值 定义和用法 示例代码 改变动态id的input值 定义和用法 val 方法返回或设置被选元素的值 元素的值是通过 value 属性设置的 该方法大多用于 input 元素 如
  • ant design pro v5 动态路由

    ant design pro v5 动态菜单 1 添加模拟数据 2 添加request请求 3 修改app tsx文件 a 第一步修改getInitialState b 第二步修改layout 4 app tsx 完整代码 5 解决icon
  • qt : day 3

    1 完成登录框的按钮操作 并在登录成功后进行界面跳转 pro QT core gui texttospeech greaterThan QT MAJOR VERSION 4 QT widgets CONFIG c 11 The follow
  • python研究生专业_用Python爬取了考研吧1000条帖子,原来他们都在讨论这些!

    写在前面 考研在即 想多了解考研er的想法 就是去找学长学姐或者去网上搜索 贴吧就是一个好地方 而借助强大的工具可以快速从网络鱼龙混杂的信息中得到有价值的信息 虽然网上有很多爬取百度贴吧的教程和例子 但是贴吧规则更新快 目的不一样 爬取的内
  • 移动Web开发入门(四) -- 移动端调试

    文章目录 移动端调试 浏览器调试 进入控制台 进入浏览器模拟器 切换测试机型 添加测试机型 改变屏幕尺寸 改变DPR 改变网络情况 改变屏幕显示大小 横 竖屏切换 真机测试 扩展 远程调试工具 vorlon js 多终端调试工具 brows
  • sql注入之报错注入

    报错注入 报错注入在没法用union联合查询时用 但前提还是不能过滤一些关键的函数 报错注入就是利用了数据库的某些机制 人为地制造错误条件 使得查询结果能够出现在错误信息中 这里主要记录一下xpath语法错误和concat rand gro
  • JVM三大子系统之类加载子系统(二)

    前置说明 由于个人能力有限 下面文章会大量整理 引用其他人的文章 我个人主要把这篇文章当成是自己的学习笔记 通过前面的文章 我们知道了 一段java代码是如何运行的 1 编译 程序员编写的java文件 编译成 class文件 2 加载 JV