自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(47)
  • 收藏
  • 关注

原创 《操作系统真象还原》 第十四章 第二部分

开头定义的struct inode_position用于记录inode所在的扇区和所在扇区的偏移量,用于寻找inode,inode_locate函数就是用于定位inode的位置,然后将inode的位置信息保存于前面定义的结构体中,inode_sync函数将inode信息同步到磁盘上,主调函数需要先申请号缓冲区,然后调用该函数,先通过inode_locate函数找到inode的位置信息,然后将inode的最新信息同步到磁盘上。sys_open函数根据文件的路径,打开文件然后返回文件描述符且只支持打开文件。

2025-11-28 14:59:08 805

原创 《操作系统真象还原》 第十四章 文件系统

若文件大于 12 个块,那就再建立个新的块索引表,新索引表称为一级间接块索引表,表中可容纳 256 个块的地址,若一级间接索引表还保存不下文件,就会去创建二级间接索引表。索引表就是块地址数组,每个数组元素就是块的地址,数组元素下标是文件块的索引,第n 个数组元素指向文件中的第n 个块,这样访问任意一个块的时候,只要从索引表中获得块地址就可以了,包含此索引表的索引结构就称为inode,用来索引、跟踪一个文件的所有块,在UINX操作系统中,一个文件必须对应一个inode,磁盘中有多少文件就有多少inode。

2025-11-21 14:32:46 950

原创 《操作系统真象还原》 第十三章 硬盘驱动程序

struct ide_channel表示通道,每个通道上挂着两个硬盘,一个主盘一个从盘,struct disk表示硬盘,使用dev_no区分是主盘还是从盘,struct partition结构体为分区结构,里面记录了起始扇区数、此分区所占的扇区数以及所属的硬盘。之前我们在bochs中创建过磁盘hd60M.img,但只用于保存内核,为了方便,我们将文件系统保存在另一个磁盘中,因此,我们需要再创建一个磁盘,创建磁盘使用bochs中的bximage命令,依次输入以下内容。

2025-11-13 17:52:32 723

原创 《操作系统真象还原》第十二章 完善内核 第二部分

sys_free就是将内存释放的函数应用在了arena内存机制上,首先,通过内存块起始地址得到对应的arena,判读是大内存释放还是小内存回收,如果是大内存释放,则调用mfree_page()函数完成释放,如果是小内存回收,先将该内存块回收到所在规格的内存块描述符的free_list中,然后再判断该arena中的内存块是否全部空闲,如果是,则通过循环遍历,将该arena中的内存块mem_block依次从free_list中移除,然后释放该arena所占的内存。接下来,就是实现上述的结构并完成初始化工作。

2025-11-07 13:21:16 686

原创 《操作系统真象还原》第十二章 完善内核

用户进程的特权级是最低的,因此,用户进程有时候需要请求高特权级的帮助,系统调用就是操作系统给用户进程提供的一些接口,每个接口都是不同的功能,用户进程需要什么功能就调用那个接口,Linux系统中的系统调用是通过中断实现的,由于系统调用很多,不能用一个中断向量号去代表一个系统调用功能,所以,将中断向量号0x80设置为处理系统调用的向量号,根据eax寄存器中存放的子功能号找到具体的系统调用函数,参数存放在ebx、ecx、edx等寄存器中。1.在syscall.c文件中添加用户进程所调用的接口。

2025-10-31 09:43:05 484

原创 《操作系统真象还原》 第十一章 用户进程

CPU执行任务时,需要将所需要的数据加载到寄存器、栈和内存中,因此,当一个任务被换下CPU时,此时寄存器中的数据内容应该保存下来,下次该任务重新上CPU时,便于恢复最新的数据内容,于是,CPU厂商就为每一个任务关联了一个任务状态段(TSS),程序员为每个人任务建立与一个TSS结构体变量,CPU会自动将任务的状态保存在该结构体变量中,再将新的任务数据状态读取到寄存器中,TSS就是任务的代表,CPU用不同的TSS区分不同的任务。并且定义TSS的选择子、同时也要定义用户程序用的代码段、数据段、栈段选择子。

2025-10-24 15:09:27 717

原创 《操作系统真象还原》 第十章 第二部分

此文件中不仅添加了新的中断处理函数,还定义多个宏和一个二维数组,多个宏表示分别表示三种控制符按键的通码和断码,用于判断,二维数组中保存了主键盘不同状态下的取值,比如按键a,当shift按键按下时,取值为A,否则,取值为a,intr_keyboard_handler()函数首先从端口0x60中读取码值,若码值为0xe0,则为双字节码值,读取下一字节码值(双字节码值的第一字节都为0xe0),scancode变量最终存放着读取的码值,通过break_code =( (scancode & 0x0080)!

2025-10-15 13:04:47 885

原创 《操作系统真象还原》 第十章 输入输出系统

因此,我们需要通过锁机制来实现线程的同步,也就是当多个线程会对同一段区域的内容修改时,只能由拥有锁的那一个线程进行操作。在该文件中,定义了struct semaphore和struct lock两个结构体,第一个结构体表示信号量,信号量表示资源的个数,此处用于实现锁,只能取0或1两个值,被称为二元信号量,该结构体中维护了一个双向链表,记录阻塞在该信号量上的线程,当拥有该信号量的线程执行结束后在该队列中进行唤醒,第二个结构体表示锁,记录了拥有该锁的线程、该锁的信号量以及锁被同一个线程所拥有的次数。

2025-10-11 20:28:27 724

原创 《操作系统真象还原》 第九章 第二部分

当执行完switch_to函数时,就会把esp指针从主线程的self_kstack指针跳到线程A的self_kstack指针,然后连续出四次栈,就会执行eip,执行ret指令,就会执行线程A所指向的函数,当线程A的时间片执行结束后,线程A的栈就会像主线程的栈一样压入一系列调用函数的返回地址,当esp指针重新指向主线程的self_kstack时,依旧是连续出四次栈,从switch_to函数中一层一层返回到之前执行到的位置继续执行。调用switch.s中定义的switch_to()函数完成线程栈的切换。

2025-10-02 16:07:05 755

原创 《操作系统真象还原》 第九章 进程管理

我们为什么要提出线程呢?实现线程调度时,我们需要将时间片到了的线程换下处理器,然后从就绪队列中选择一个线程上处理器,这里的就绪队列就是我们内核重要的数据结构,就绪队列就是一个双向链表,但与我们之前所学的双向链表有些许不同,它将数据与链表的结点分离开来,使得整个链表的大小更小,只存在prev和next指针,根据链表结点的地址计算出整个结构体的起始地址,从而访问数据。2.进程相当于是一种执行流的集合,最少包含一种执行流,在执行流之间是相互独立的,但它们共享进程的资源,是处理器的执行单位,这些执行流就是线程。

2025-10-01 12:33:47 890

原创 《操作系统真象还原》 第八章 内存管理 第二部分

接下来定义了三个内存池,分别为kernel_pool 内核物理地址内存池 user_pool 用户物理地址内存池 kernel_vaddr内核虚拟地址内存池,函数mem_pool_init()为内存池进行初始化操作,参数为内存的总容量,在第五章的内容中我们计算过内存容量并存放到了地址0xb00处,通过内存总容量为三个内存池的各个参数进行赋值,函数vaddr_get()用于向虚拟地址内存池中申请pg_cnt个虚拟页,返回虚拟地址,函数palloc()用于向物理地址内存池申请一页物理页。memory.h文件。

2025-09-23 16:08:41 341

原创 《操作系统真象还原》 第八章 内存管理

makefile文件的只要功能就是定义文件之间的依赖关系,当某个文件被更新时,只需根据所规定的规则对与这个文件有依赖的文件进行修改,其他文件无需修改。debug.h文件中定义了ASSERT宏,用于判断所传入的条件是否成立,若不成立则调用PANIC宏,PANIC宏本身就是panic_spin()函数,此处所传入的参数为__FILE__,__LINE__,__func__,__VA_ARGS__,前三个参数编译器提前定义好的,分别代表被编译的文件名,被编译文件的行数以及被编译的函数名。

2025-09-19 15:53:00 582

原创 《操作系统真象还原》 第七章 中断

该段代码中struct gate_desc结构体就是中断描述符,它的成员变量与上面的中断描述符结构对应,中断描述符表就是一个struct gate_desc结构体类型的数组,pic_init函数用于初始化8259A中断控制器,对端口进行读写操作定义使用规则,make_idt_desc函数的第一个参数为中断描述符结构体、第二个参数为该中断描述符的属性,第三个参数为中断处理程序的起始地址,该函数的作用就是为第一个参数的结构体属性赋值,使得发生中断时可以跳转到其对应的中断处理程序的起始地址执行程序。

2025-09-10 20:01:53 639

原创 《操作系统真象还原》第六章 实现打印函数

Address Register 作为数组的索引(下标),Data Register 作为寄存器数组中该索引对应的寄存器,它相当于所对应的寄存器的窗口,往此窗口读写的数据都作用在索引所对应的寄存器上。打印整数函数与打印字符函数也密不可分,如数字9,只需要转换为字符‘9’,就可以调用put_char函数进行打印,我们将数字减去0或者10得到数字与字符‘0’或者字符'A'的偏移量,再加上各自的ASCLL码值就可以将数字转换成字符。(1) 保存寄存器环境,定义一个8字节的内存缓冲区,用于保存数字内容。

2025-08-22 17:51:04 689

原创 《操作系统真象还原》 第五章 保护模式进阶

1.获取物理内存容量操作系统需要管理硬件,自然就需要知道自己有哪些硬件可用以及这些硬件的信息。是一个非常重要的信息,操作系统获得内存容量的方法通常在实模式工作时就调用BIOS中断来获取,然后存储在内存中,进入保护模式后再使用这些信息(因为保护模式不能使用BIOS中断)。

2025-08-01 18:58:38 677

原创 《操作系统真象还原》 第四章 保护模式入门

选择子:在实模式下,段寄存器保存的就是段基址,而保护模式下,段基址已经保存在了段描述符中,段寄存器中再保存段基址是没有意义的,因此段寄存器中保存的是选择子,选择子相当于一个索引值,用此索引值在段描述符表中索引相应的段描述符,这样,便在段描述符 中得到了内存段的起始地址和段界限值等相关信息。保护模式是在地址总线和数据总线为32位的环境下运行的,其寻址空间达到了2的32次方,4GB,在内存寻址方法得兼容老方法(段基址:段内偏移量)且要达到4GB的寻址空间,寄存器就得与时俱进,将寄存器宽度提升到32位。

2025-07-25 18:26:58 495

原创 《操作系统真象还原》第三章 完善MBR

以这两句代码为例,上文中提到一个字符占两个字节且低字节表示字符内容,高字节表示字符的前后背景颜色 ,第一句表示字符内容为‘1’,第二句表示将0xA4赋值给第二个字节,将0xA4转换为二进制为10100100,由于采用小端字节序进行保存(00100101),根据上述的字符显示规则可知,该字符背景色为绿色且闪烁,字符前景色为红色。高字节低4位是字符前景色,也就是字符的颜色(RGB是红蓝绿三种颜色的调和,I位表示是否高亮),高字节高4位是字符的背景色(RGB是红蓝绿三种颜色的调和,K位控制是否闪烁)。

2025-07-18 19:06:00 586

原创 《操作系统真相还原》学习笔记 第二章 编写MBR主引导记录

在Intel8086计算机开机的一瞬间,cpu的cs:ip寄存器被强制初始化为0xF000:0xFFF0,由于开机的时候处于实模式,此时采用的分段访问机制为段基址*16(即左移4位)+偏移量,于是0xF000:0xFFF0相当于地址0xFFFF0,根据下图实模式下的内存布局可知,该地址为BIOS的入口地址。4、在3的基础上是,那么就将该扇区内容加载至0x7c00内存处。MBR的大小必须是512个字节,且最后两个字节的内容分别为0x55和0xaa,接下来,编写一段简单的MBR来实现在屏幕上显示几个字符。

2025-07-11 15:20:41 325

原创 《操作系统真相还原》学习笔记 第一章 配置环境

1.概述:实现一个操作系统需要在特定的环境下完成,第一章主要讲解了我们需要用到的各种的组件,从虚拟机的环境搭建到bochs的安装,最后成功运行MBR的测试代码。bochs虚拟机想对于VMware虚拟机而言,bochs虚拟机所有的组件全部由软件实现,更有利于对操作系统进行调试。--prefix=后的路径需要改为自己Linux操作系统中bochs文件夹所在的绝对路径。并执行以下命令写入启动磁盘中(if=、of=后的路径依然需要修改为自己的路径)bochs虚拟机安装完成后,进入bochs文件夹。

2025-07-10 21:40:00 751

原创 线程池相关接口和实现类

3.如果当前线程数大于核心线程数并且线程池为RUNNING状态,将线程任务添加到workQueue工作队列中,等待某个空闲工作线程获取并执行任务。5.这次在创建新的Worker工作线程时,会判断当前线程池的线程数是否超过最大线程数,如果超过,则返回false,代表创建失败,执行拒绝策略。1.首先获取线程池的工作状态和工作线程数(线程池用一个32位的整数代表工作状态和工作线程数,前3为代表工作状态,后29位代表工作线程数)。的线程池实现类,通过分叉合并的方式,将一个大任务拆分成多个小任务,并且为。

2023-12-12 16:20:27 222

原创 TCP协议

(2)如果采用二次握手,当第一次连接请求发送后,由于网络等原因,客户端迟迟没有收到服务器的确认请求,由于TCP的重发机制,客户端会发送第二次连接请求,然后服务器对第二次连接请求进行确认后,当第一次连接请求到达服务器时,服务器以为客户端进行重新连接,向客户端再次发送确认请求,客户端此时不会处理服务器第二次的确认请求,则服务器会一直等待着客户端的回复,造成服务器的无效等待,如果频繁发送连接请求,可能会造成服务器停止响应。第一次挥手:有客户端向服务器发送首部格式为FIN=1,ACK=0的释放连接请求。

2023-09-23 18:07:31 172

原创 Spring的AOP

如果需要指明参数: int ========>int,String====>java.lang.String,需要指定完全限定名,通常都只给业务层的所有方法配置aop。连接点(Join point):表示在程序中明确定义的点,典型的包括方法调用,异常处理程序块的执行,也就是所有的方法,不管是接口的抽象方法,还是实现类的重写方法。上面代码中,我们定义了两个类,一个为业务类进行整数计算,另一个为日志切面类,为每个业务方法添加日志功能,接下来,我们通过xml配置文件的方式进行配置。

2023-08-28 11:15:55 146

原创 Spring的DI依赖注入

1.概述:在上篇文章中,我们了解了Spring的IOC思想并且通过<bean>标签配置类信息,通过IOC容器创建对象并获取使用,但是IOC容器是通过无参构造方法创建出的对象,属性值均为null,所以我们就要通过DI依赖注入来进行属性的赋值。通过以上两种自动装配的实现,也可以将IdCard类型的对象注入到Student类的card属性,这也是我们依赖注入的本质,类A中存在类B的属性,IOC容器中存在着类A和类B的bean对象,有IOC容器管理类A和类B的依赖关系。用于引用IOC容器中的bean对象。

2023-08-25 20:27:43 131

原创 Spring的IOC容器

我们通过new关键字直接创建出Driver类的对象,此时代码的耦合度是最高的,因为一旦Driver类被删除了,代码无法运行,所以我们经常使用Class.forName()基于反射的方式加载驱动类。在这次的代码中,我们使用Class.forName()方法基于反射加载驱动类,耦合度有所降低,但是驱动类的完全限定名在代码中写死了,如果改变驱动类,必须修改源代码。为类的完全限定名,IOC容器在底层就会进行读取配置文件中的信息,然后通过反射技术创建出对象返回,接下来,就让我们获取Student类的对象。

2023-08-23 21:21:34 88

原创 ResultMap标签的使用

从Order订单的角度出发,一个订单只能属于一个用户,属于一对一关系,在查询Order订单信息时,我们也需要查询出所对应的User用户信息,可以通过多表联查的方式将数据一次性查出,然后定义映射关系,此文章使用的是级联查询的方式。在该resultMap映射关系定义时,大部分与一对一关系的定义是一致的,唯一不同的是,Order对于User用户来说是一对多的,也就是说,在User类中,存在一个Order订单的List集合,所以,在一对多的关系中,使用。定义映射关系,该标签的属性与<association>标签。

2023-08-21 20:47:00 275

原创 MyBatis框架基本使用

sqlSession.getMapper()方法就使用到了动态代理来生成UserMapper接口的实现类,无需我们调用sqlSession.selectList()一系列的方法来执行sql语句,直接调用实现类的方法即可。在映射文件中定义了namespace命名空间,sql语句写在对应的标签中,sql语句的标签必须在<mapper></mapper>标签之间,sql标签需要。上述的sqlSession.selectList()的参数为sql语句的唯一标识,即mapper映射文件的。

2023-08-16 22:05:41 127

原创 TreadLocal实现线程之间数据隔离

在上面的代码中,我们首先创建出了一个ThreadLocal类型的roleLocal对象, 然后创建出两个不同的线程,在线程中先使用roleLocal分别保存不同的角色名称,然后调用show()方法通过roleLocal取出角色名称,再调用Sample的dosth()方法通过roleLocal取出角色名称。从运行结果看出,两个线程分别保存自己的角色名称,实现了线程之间的数据隔离,在show()方法和Sample类的dosth()方法之间,ThreadLocal实现了同一个线程中不同方法之间的数据传递。

2023-08-15 21:26:06 580

原创 实现动态代理

动态代理基于反射技术实现,可以在程序运行期间动态的创建出代理对象,动态代理分为jdk自带的动态代理和cglib动态代理。在学习动态代理之前,我们先了解一下代理模式是什么,代理模式就是指我们不会直接去调用目标对象的方法,而是通过一个类代理目标对象,然后通过代理对象去调用目标对象的方法,在代理对象中可以对目标对象的方法进行增强,避免对目标对象的代码造成污染。当我们需要对真实主题角色的方法进行调用时,不再直接调用真实主题角色的方法,而是通过代理类,让代理类去调用真实主题的方法,同时进行了方法的增强。

2023-08-11 21:13:46 103 1

原创 RSA非对称加密算法

解密方法中,使用自己的私钥进行解密,加密方法表示该对象需要发送消息给对方,所以必须使用对方的公钥加密,解密方法表示该对象收到了对方使用它的公钥进行解密的密文,所以必须使用自己的私钥进行解密。,当使用A同学的公钥加密后得到的密文,只有A同学使用自己的私钥才能解密,如果别人知道了他的公钥,也不能计算出对应的私钥,所以使用非对称加密算法时,需要使用对方的公钥进行加密。,特点为加密的速度和效率高,但由于双方使用的都是同样的密钥,安全性得不到保证,非对称加密算法加密和解密使用的是。对称加密算法加密和解密使用的是。

2023-08-03 22:38:26 210

原创 DH秘钥交换算法

如上图所示, 加密和解密双方都会拥有自己的私钥和公钥,公钥是公开的,私钥是只有自己知道的,Alice将自己的私钥与g,p两个参数进行计算得到自己的公钥,然后将自己的公钥和g,p两个参数通过网络发送给Bob,Bob根据Alice发送的g,p参数与自己的私钥进行相同计算得到他的公钥,再将他的公钥发送给Alice,最后,双方根据各自的私钥与对方发送来的公钥进行相同的数学计算得到共享秘钥(真正进行加密和解密的秘钥)。在Person类中,分别保存了每个人对应的私钥,公钥和共同的秘钥,在构造方法中通过。

2023-07-27 21:57:33 498 1

原创 CopyOnWriteArrayList核心代码阅读

通过上面代码的阅读, 可以看出CopyOnWriteArrayList集合在增,删,改的方法都加了锁,并且都会将原来的数组复制一份,在新的数组上修改好了之后才设置为集合存储数据的array数组,所以在对CopyOnWriteArrayList集合进行写操作的时候,保证了线程安全,但在每次写操作时,都要复制数组,影响性能。锁,并且在进行写操作的同时,允许进行读操作,还可以多个线程并发进行读操作,读取效率高,性能高于Vector集合。Vector集合也是线程安全的集合,由于Vector集合使用的是。

2023-07-22 20:09:55 113

原创 synchronized锁和ReentrantLock锁的区别

使用synchronized关键字加锁之后,如果有线程想执行代码块中的代码,必须获取该代码块所指定的锁后才能执行,当add()方法执行时,dec()方法所在的线程不能获取锁,所以只有add()方法执行完释放锁后,dec()方法所在线程才能得到锁,dec()方法才可以执行,同样的,在dec()方法执行过程中,其它线程也不能干扰dec()方法的执行,只能等到dec()方法执行结束释放锁后。dec()方法的加锁和释放锁与之一样,需要强调的是,在add()方法和dec()方法中使用到的锁为同一个。

2023-07-19 21:31:11 218 1

原创 线程池的执行流程

以上面的案例代码来看,当我们提交第一个线程任务时,线程池中还没有线程,所以会创建出一个核心线程来执行该线程任务,随后的第二到五个线程任务都会创建出一个核心线程,此时线程池中的线程数已达到。(4)如果达到最大线程数,就会执行拒绝策略,否则,线程池就会新创建出一个线程对象去执行线程任务,与第(2)步不同的是,这次新创建的线程为。(1)当新的线程任务提交到线程池后,线程池会判断当前线程池中是否有空闲的线程,如果有,就将空闲线程分配给线程任务执行。(2)如果没有空闲线程,线程池就会判断当前线程池中的线程数。

2023-07-18 21:33:12 282 1

原创 线程的创建方式

从上面的运行结果可以看到,当主线程打印到数字5时,子线程才开始执行,而当下次执行时,可能结果就会发生变化,如果想让线程插队,可以调用线程对象的。从运行结果中看出,主线程在子线程之前结束,那是因为当子线程启动后,主线程和子线程的运行由操作系统决定,只有当进程中的所有线程运行结束后,该进程才会结束。方法的SubThread类就是我们自己定义的线程类,在这个子线程中,实现的业务逻辑为打印1-10的数字,在主线程中,我们创建出该线程的线程对象,然后调用。不会启动子线程,进程中依旧只有一个主线程(守护线程除外)。

2023-07-17 20:48:58 154 1

原创 AES算法的两种工作方式

将上面的代码不管执行多少次,只要不修改秘钥和明文的内容,得到的加密结果都是一致的,这样就使得安全性降低,在下面的CBC工作模式中,就会在每次加密时根据随机产生的IV参数使得相同的秘钥和明文,每次加密得到的结果都是不一样的。上面的两次运行结果可以看出在CBC工作模式下,相同的明文和秘钥由于随机的iv参数不同,每次的加密结果不同,相比于ECB工作模式,安全性得到了提高。上面的代码为CBC工作模式下进行的操作,与ECB工作模式相差不多,只是在加密和解密中添加了随机的。秘钥对象,然后调用cipher对象的。

2023-07-15 19:58:02 491 1

原创 java反射机制

(4)getDeclaredMethod(String name,Class...):根据方法的名字和参数获取类中定义的字段(不包括父类的)(2)getMethod(String name,Class...):根据方法的名字和参数获取指定的public修饰的方法(包括父类的)(2)getField(String name):根据字段的名字获取指定的public修饰的字段(包括父类的)我们得到字段的对象后,最主要的操作就是向该字段存值或得到该字段的值,可以使用Field类的set()和get()方法完成。

2023-07-14 20:25:22 159 1

原创 哈希加密算法

我们根据字节数组可以直接创建出密钥对象,当我们数据库中存放的是密钥字符串时,就需要将字符串转换为对应的字节数组,然后创建出密钥对象,因为我们在字节数组转字符串时,是将一个字节转换成了两个十六进制的字符,所以在字符串转字节数组时,应该每两个十六进制字符转换成一个字节。在我们校验数据时,需要用相同的密钥和数据进行加密,然后与数据库中存放的加密结果进行比对才能得到数据的准确性,而往往数据库中存放的是密钥的内容(字节数组或字符串),在加密过程中用到的是。2.当输入内容不一样时,输出内容大概率不一样。

2023-07-10 19:31:37 1660 2

原创 java实现发送邮件

在上面的代码中,我们将与服务器连接的信息封装在Properties对象中,在创建Session对象时,需要传入两个参数 ,第一个参数就是我们封装的服务器连接信息,第二个参数为用户认证对象,因为Authenticator为抽象类,所以创建一个匿名子类对象并将邮箱账号和授权码传入。在生活中,我们经常会发送带有附件的邮件,接下来,我们就通过java程序发送带有附件的邮件,要发送带有附件的邮件,不能直接设置正文内容,需要用到。我们有时候需要在邮件的正文中嵌套图片,那么这个功能在java程序中如何实现呢?

2023-07-08 18:51:12 7689 5

原创 FTP协议网络编程

1概述:FTP协议为文件传输协议,在java程序中可以作为客户端将文件上传到FTP服务器中,也可以从服务器中下载文件到本地磁盘。(3)启动服务器,并在浏览器地址栏中输入服务器的主机号和端口,通过自己设置的账号和密码访问服务器。方法上传文件,第一个参数为上传到服务器后在服务器中的名称,第二个参数为读取本地文件的输入流。文件上传时,连接和登录服务器与上面的代码一致,在上传文件之前,需要通过FTPClient的。方法下载文件,第一个参数为文件在服务器中的名称,第二个参数为存放下载文件的输出流。

2023-07-08 16:22:30 377

原创 Super关键字的用法

其实,在子类Son中,不管我们使用super.name,this.name还是name,编译器都会定位到父类Base的name属性,所以在访问属性的时候,可以不使用super关键字。可以看到我们在上面的代码中没有显式的调用父类的构造方法,那是因为编译器在编译过程中,会自动在第一行加上super()调用父类默认的无参构造。1.概述:在面向对象中,继承是三大特征之一,继承过程中,子类如果想调用父类的属性和行为可以通过super关键字调用,在java中super关键字最常用的是调用父类的构造方法。

2023-07-07 21:19:42 179 1

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除