关于Object 0 = new Object() 的追魂九连问

文章目录

  • 对象的创建过程
  • 对象的组成
  • 解析普通对象
    • **结果分析:**
      • 给对象添加属性
        • 注意事项
      • 补充
      • jvm压缩指针
        • 栗子:
  • 对象头包含什么
  • 对象怎么定位?
    • **句柄方式和直接引用的优缺点:**
  • 对象怎么分配?
  • 为什么hotspot不使用c++对象来代表java对象?
  • Class对象是在堆还是在方法区?
  • DCL要不要加volatile问题
    • DCL
    • 指令重排
    • volatile

来源于:B站马士兵的jvm视频总结!!

1、解释一下对象的创建过程?(半初始化)

2、DCL要不要加volatile问题?(指令重排)

3、对象在内存中的存储布局?(对象与数组的存储不同)

4、对象头具体包含什么?

5、对象怎么定位?(直接、间接)

6、对象怎么分配?(栈上-线程本地-Eden-Old)

7、Object 0 = new Object()在内存中占多少个字节

8、为什么hotspot不使用c++对象来代表java对象?

9、Class对象是在堆还是在方法区?

对象的创建过程

当执行 Object o = new Object(); 这行代码时,一个新的 Object 对象会被实例化,而这个对象实例会存储在堆内存中。Object o 实际上是一个引用变量,它存储在栈内存中,指向堆内存中的那个 Object 对象。通过这种方式,我们可以通过引用变量 o 来访问和操作堆中的 Object 对象。当 o 超出其作用域或被重新赋值时,堆中的 Object 对象仍然存在,直到垃圾收集器回收不再使用的对象。

  1. new Object():这是一个对象的实例化过程。new 关键字用于在内存中分配空间来存储新的对象。Object() 是一个构造函数调用,用于初始化 Object 类的新实例。
  2. 对象的内存分配:new Object() 表示在Java堆中分配了一块内存空间,用于存储一个新的 Object 对象。
  3. 构造函数的执行:一旦分配了内存空间,就会调用 Object 类的构造函数。在这种情况下,Object 类是Java中所有类的基类,它的构造函数是一个无参构造函数,因此没有任何参数传递。
  4. 初始化对象:在构造函数执行完毕后,对象被初始化为 Object 类的实例。此时,Object o 引用变量被赋值为指向这个新创建的对象。

注意事项:

在实际开发中,我们通常不会直接使用 Object 类的实例,而是创建自定义类,然后实例化自定义类的对象来进行具体的业务操作。Object o = new Object(); 这种形式通常在示例代码或一些基础概念演示中使用。

当刚new出来一个对象时,所有成员变量都有一个默认值,只有当调用构造方法时才会赋值;例子:

public class test {
    int n = 8;
}
  1. 申请空间,给默认值0,而不是8,
  2. 调用构造方法赋值
  3. 引用,建立关联

对象的组成

img

1、markword:

8字节

2、class pointer(类型指针)

4字节

意思是当你new的是什么对象时,它指向的就是什么.class,规定一个对象具体是什么对象

例如:

new User(),那它指向的就是User.class

3、instance data(实例数据)

放入一个对象的成员变量,比如:

当User()对象里有一个属性是String name;时,那么这个name这个属性就是放在这里面

4、padding(对齐)

就是为了让数据对齐,假如前面那3个部分加起来不能被8字节整除,则自动补充尾数,直到能被8整除

为什么是8字节呢?因为8字节是64个bit,我们虚拟机或者说电脑来说就是64位,所以一次性存储64位对它来说是最方便的

比如我装货卸货的时候必须是一次64个,那当我的货只有63个时,我将补充一个空的货

解析普通对象

1、我们采用JOL(Java Object Layout)类库来解析对象,依赖:

<!-- https://mvnrepository.com/artifact/org.openjdk.jol/jol-core -->
<dependency>
    <groupId>org.openjdk.jol</groupId>
    <artifactId>jol-core</artifactId>
    <version>0.9</version>
</dependency>

2、使用:

package com.example.demo.web;

import org.openjdk.jol.info.ClassLayout;

/**
 * com.example.demo.web
 *
 * @version Id: test, v 0.1 2023/7/14 14:19  Exp $
 */
public class test {
    private static class T{

    }
    public static void main(String[] args) {
        T t = new T();
        System.out.println(ClassLayout.parseInstance(t).toPrintable());
    }
}

3、运行结果:

image-20230726155157224

结果分析:

可以看到第一行和第二行都是4个字节,而且代表的是对象头,前面我们说markword是由8个字节组成,那么第一行和第二行加起来就是代表markword

第三行代表的是class pointer(类型指针),所以可以通过value的4个字节找到T.class

第四行显示loss due to the next object alignment代表的是补齐4个字节,让8整除

image-20230726155426459

所以可以得出Object 0 = new Object()一共占用16个字节,也就解决了第7个问题

给对象添加属性

我们给对象添加一个int a,那么这个对象占多少个字节呢?

private static class T{
	int a;
    }

其实很好计算,int类型在java中就占4个字节,所以我们的执行结果是:

image-20230726164100739

这里的第4行就不是补齐了,是instance data(实例数据)

因为加起来正好16个字节,可以被8整除,所以没有补齐这一部分

Java中8大数据类型对应的字节大小:

类型字节位数
byte
short16
int32
long64
float432
double864
char216
boolean1(通常是1个)8
String464

注意事项

  1. boolean类型虽然只占1个字节,但因为在jvm中会把它转换为int类型,所以它会补齐3个,所以也是占4个字节,byteshort同理;这重情况叫做内部对齐
  2. String字段填写值,比如在T对象中添加属性String s = "hello",它也是占4个字节,因为hello是存在字符串常量池中的,和对象本身是没关系的,只是可以通过这4个字节在常量池中找到对应字符

补充

jvm的指针长度是多少,由什么来决定呢?

长度的意思也就是说电脑的寻址能力有多强,能有多少中bit组合。每种组合就代表一个地址

由电脑的位数来决定:

image-20230726170320686

随着电脑的运行内存的增大,就必须由高位的操作系统才能支持,比如32位的电脑,最大支持的运行内存就是2的32次方,也就是4G

那为什么String的指针只有4个字节呢?也就是32位呢?

因为使用了压缩指针,因为大多数的机器,用32位已经绰绰有余,就是为了省空间

jvm压缩指针

我们可以看到java启动参数有一个-XX:+UseCompressedClassPointers意思是启用压缩类指针,一般我们启动jar包时都会携带这个参数;(默认)

如果没有,普通类不是由4个部分组成吗!那么它其中的class pointer类型指针,就是8个字节了,而不是4个字节

以及-XX:+UseCompressedOops,oops指的是:ordinary object pointers (普通对象指针)一样进行了压缩,也就是String这样的对象

栗子:

1、把压缩指针关掉:

image-20230726173238081

把+改成-即可

2、运行结果:
image-20230726173400519

可以看到第1、2、3、4行全是Object header,第1、2代表的是markword,第3、4行就代表的是类型指针了,多了4字节!

对象头包含什么

由上面我们可以得知:对象头包含一个markwordclass pointer类型指针

class pointer在上面已经说过,就是地址,比较简单,所以一般这样问的话就是问markword中有什么?

image-20230727155924514

回收时需使用三色标记,当前 处于什么颜色就存在markword中的GC标记信息中,以及分代年龄

我们可以看到markword中还存着hashCode,当你调用hashCode时才会存储,不然为null,这样设计的目的就是,调用一次hashCode之后,这个hashCode是不变的,下次再调用就是直接拿markword中的值了,不需要重新计算;

1.hashcode调用前后对比:

image-20230727160931411

2.锁前后对比:

image-20230727161508889

发现上完锁之后,markword信息发生了变化,所以锁信息是存放在markword中的

到这里第3、4、7个问题得到了解决!!!!

对象怎么定位?

两种方式:

image-20230727163253123

句柄方式(Handle-Based Approach)是一种内存管理方式,用于处理对象在内存中的定位和访问。在句柄方式中,对象的引用由两部分组成:句柄和实际对象。

具体来说,句柄方式中有两级间接寻址:

  1. 句柄(Handle):每个对象的引用变量并不直接指向对象本身,而是指向一个句柄对象。句柄对象是一个固定大小的数据结构,其中包含了实际对象的地址(或者称为指针)和其他元数据信息。实际引用变量中存储的是指向句柄对象的引用。
  2. 实际对象:句柄对象中包含了指向实际对象的地址。通过这个地址,可以访问到实际的对象数据。

通过引入句柄对象,Java虚拟机可以更好地管理内存。由于句柄对象是固定大小的,它们可以在堆中更容易地进行移动和重新分配。而实际对象的地址则可以在句柄中进行更新,而无需修改引用变量的值。

Java曾经采用句柄方式作为一种内存管理方式,但从JDK 1.4版本开始,大部分的Java虚拟机实现转向使用直接引用的方式,即直接将引用变量指向实际对象,避免了句柄对象的额外开销,提高了访问效率。目前,大多数Java虚拟机都不再使用句柄方式。句柄方式在Java之外的其他编程语言和部分特定的嵌入式系统中可能仍然有应用。

句柄方式和直接引用的优缺点:

因为GC的回收涉及到对象的移动,所以对应的需要修改指针地址

存管理方式,在不同的情况下各有优缺点。下面是它们各自的优缺点:

句柄方式的优点:

  1. 内存管理灵活:句柄对象的固定大小使得内存管理更加灵活。因为句柄对象可以在堆中更容易地移动和重新分配,从而减少了碎片化问题,有利于提高内存的利用率。
  2. 安全性:句柄对象可以提供更好的安全性。由于引用变量存储的是指向句柄对象的引用,而不是指向实际对象的地址,可以在运行时做更多的安全检查和控制,防止悬空指针和野指针等问题。

句柄方式的缺点:

  1. 性能损失:由于句柄对象和实际对象之间需要进行两级间接寻址,这增加了访问对象数据的开销,导致性能上的损失。尤其是在频繁访问对象时,句柄方式可能会导致额外的开销。
  2. 需要额外内存:句柄方式需要为每个对象都分配额外的句柄对象,这会导致额外的内存开销。这在对象数量较多时可能会成为问题。

直接引用的优点:

  1. 性能更高:直接引用避免了句柄方式中的两级间接寻址,直接将引用变量指向实际对象,因此访问对象数据更加高效,减少了额外开销,提高了性能。
  2. 内存开销较小:直接引用不需要额外的句柄对象,节省了内存开销。这对于对象数量较大或内存有限的场景非常有利。

直接引用的缺点:

  1. 内存管理相对困难:直接引用使得内存管理相对困难,因为实际对象在堆中的位置可能会发生变化,导致引用的失效。为了解决这个问题,需要引入更复杂的内存管理策略,如压缩算法等。

综合来看,直接引用方式在性能和内存开销上更优,因此成为目前主流的内存管理方式。但是句柄方式在一些特定的场景下可能仍然有一定的优势,尤其是在安全性和内存管理灵活性方面。不同的编程语言和系统根据具体需求可能会选择适合的内存管理方式。在Java中,目前的主流Java虚拟机都采用了直接引用的方式。

对象怎么分配?

image-20230727173655824

  1. 当我们new一个对象时,先会尝试是否能在栈上分配,如果可以,就直接存在栈上,不行才会在堆空间(通过逃逸分析来判断是否能在栈上分配)

    **逃逸分析:**指的是一个对象是否被传递到了方法外部,即对象的引用是否在方法的生命周期之外继续存在。如果对象没有逃逸,它的生命周期仅限于方法的执行过程,那么编译器可以选择将该对象在栈上分配内存而不是在堆上分配。这样做的好处是,在栈上分配的对象可以随着方法的退出而自动销毁,无需垃圾收集器的介入,减少了内存的使用和垃圾收集的开销,从而提高了程序的性能。

  2. 判断对象是否大,如果过大则直接分配到老年代,(通过JVM参数控制)

  3. 经过TLAB分配,进入到新生代(E区-诞生区)

    TLAB:代表线程本地分配缓冲区(Thread-Local Allocation Buffer),是Java虚拟机(JVM)中的一种内存分配优化技术。

    在Java中,对象的创建通常是在堆内存中进行的。为了提高对象的分配效率,JVM引入了TLAB机制。TLAB是每个线程私有的一块内存区域,用于在线程本地进行对象的分配。每个线程都有自己的TLAB,从而避免了多线程竞争分配内存的问题。

    需要注意的是,TLAB机制只在启用了线程本地分配缓冲区的情况下才会生效。可以通过JVM参数来控制TLAB的启用和大小,例如使用-XX:+UseTLAB来启用TLAB,使用-XX:TLABSize来设置TLAB的大小。在大多数情况下,JVM会根据硬件和应用程序的特点自动调整TLAB的大小。

  4. 在E区经过GC之后,回收掉了就结束,没回收掉就会进入S区(也就是幸存者区域)

  5. 如果再次GC还没清除掉,则判断年龄大小,达到赋值则进入老年代,没有则进入S2,(第二个幸存者区域),如此反复,直到GC回收掉

为什么hotspot不使用c++对象来代表java对象?

hotspot指的是Java虚拟机(Java Virtual Machine,JVM)的一种实现,HotSpot虚拟机以高性能为目标,通过即时编译(Just-In-Time Compilation,JIT)技术来将Java字节码转换为本地机器码,从而提高Java应用程序的执行速度。

  1. C++对象有一个virtual table 这个是java对象所没有的。所以相对应的c++的对象会占用内存更多
  2. 对象头信息:Java对象在HotSpot中包含对象头信息,用于存储元数据,如哈希码、锁状态、GC信息等。这些信息在C++对象中无法直接表示。
  3. 垃圾回收:Java虚拟机需要进行垃圾回收来管理内存,回收不再使用的对象。而C++没有垃圾回收机制,需要手动管理内存。(HotSpot中存有GC信息)
  4. 跨平台性:Java是一种跨平台的编程语言,而C++的对象模型和内存布局在不同平台上可能会有差异。使用C++对象来表示Java对象可能会导致不同平台之间的兼容性问题。
  5. JNI交互:Java虚拟机支持与本地代码的交互,通过JNI(Java Native Interface)可以调用C++代码。为了与Java对象交互,Java虚拟机需要一种独立于C++对象的对象表示方式。

Class对象是在堆还是在方法区?

在堆中

存放在方法区当中的是类的元数据,即类加载器从class文件中提取出来的类型信息、方法信息、字段信息等。元数据中又保存着指向class对象的引用。

参考文章

DCL要不要加volatile问题

需要!

cpu不一定是按照顺序执行程序,可能会出现乱序

DCL

DCL(双重检查锁定),经典例子是单例模式,双重检查锁定利用了以下两个原则:

  1. 减少同步开销: 通过首先检查实例是否已经创建,如果没有创建,再进行同步操作,从而减少了不必要的同步开销。
  2. 保证线程安全: 在同步块内进行实例的创建操作,确保只有一个线程能够成功创建实例。
public class Singleton {
    private volatile static Singleton instance; // 使用volatile确保可见性

    private Singleton() {
        // 私有构造方法
    }

    public static Singleton getInstance() {
        if (instance == null) { // 第一次检查,避免不必要的同步
            synchronized (Singleton.class) {
                if (instance == null) { // 第二次检查,确保只有一个线程创建实例
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

指令重排

在第一个问题我们说了Object 0 = new Object()大体分为三步:

  1. new 申请空间,半初始化对象,也就是给默认值
  2. 调用构造方法,赋值
  3. 引用,建立关联

这是按照正常顺序执行,但CPU会出现乱序执行,就一定会出现这三步乱序的问题,比如132的顺序,假如这种情况发生(还是拿上面单例模式举例),就会出现还没完成初始化,只是半初始化就会得到一个对象

image-20230810173606371

volatile

volatile 是一个关键字,用于修饰变量,它的作用是确保变量在多线程环境下的可见性和禁止指令重排。volatile 变量具有以下作用:

  1. **可见性(Visibility):**当一个变量被声明为 volatile 时,任何线程对该变量的修改都会立即对其他线程可见,即使是在不同的CPU核心上。这可以确保当一个线程修改了 volatile 变量的值后,其他线程能够立即看到最新的值,避免了线程之间的数据不一致问题。
  2. **禁止指令重排:**在多线程环境下,编译器和处理器为了提高执行效率可能会对指令进行重排,这种重排可能会影响多线程程序的正确性。通过将变量声明为 volatile,可以防止编译器和处理器对该变量相关的指令重排,从而确保操作的顺序符合程序员的预期。

volatile

volatile 是一个关键字,用于修饰变量,它的作用是确保变量在多线程环境下的可见性和禁止指令重排。volatile 变量具有以下作用:

  1. **可见性(Visibility):**当一个变量被声明为 volatile 时,任何线程对该变量的修改都会立即对其他线程可见,即使是在不同的CPU核心上。这可以确保当一个线程修改了 volatile 变量的值后,其他线程能够立即看到最新的值,避免了线程之间的数据不一致问题。
  2. **禁止指令重排:**在多线程环境下,编译器和处理器为了提高执行效率可能会对指令进行重排,这种重排可能会影响多线程程序的正确性。通过将变量声明为 volatile,可以防止编译器和处理器对该变量相关的指令重排,从而确保操作的顺序符合程序员的预期。

需要注意的是,尽管 volatile 能够解决一些多线程问题,但它并不能完全取代锁。volatile 只适用于某些特定的场景,如标识状态变量、控制开关等,它无法保证复合操作的原子性,也无法解决一些更复杂的线程同步问题。对于一些需要保证原子性和临界区操作的情况,还是需要使用锁或其他线程同步机制

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/68143.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

QT的信号槽的四种写法和五种链接方式

目录 四种信号槽写法&#xff1a; 五种连接方式&#xff1a; 实例&#xff1a; 常见错误及改正&#xff1a; 错误1: 未连接信号与槽 错误2: 信号和槽参数不匹配 错误3: 未使用Q_OBJECT宏 错误4: 跨线程连接未处理 在Qt中&#xff0c;信号&#xff08;Signal&#xff09…

Stephen Wolfram:让 ChatGPT 真正起作用的是什么?

What Really Lets ChatGPT Work? 让 ChatGPT 真正起作用的是什么&#xff1f; Human language—and the processes of thinking involved in generating it—have always seemed to represent a kind of pinnacle of complexity. And indeed it’s seemed somewhat remarkabl…

go-admin 使用开发

在项目中使用redis 作为数据缓存&#xff1a;首先引入该包 “github.com/go-redis/redis/v8” client : redis.NewClient(&redis.Options{Addr: config.QueueConfig.Redis.Addr, // Redis 服务器地址Password: config.QueueConfig.Redis.Password, // Redis 密码&…

Vue自定义指令使用

本篇文章讲述使用Vue自定义指令&#xff0c;并在项目中完成相应功能。 在平常Vue脚手架项目中&#xff0c;使用到 自定义指令较少&#xff0c;一般都是使用的自带指令&#xff0c;比如 v-show 、v-if 、 v-for 、 v-bind 之类的。这些已经能够满足大多数项目使用。更多的可能也…

springboot+mybatis实现简单的增、删、查、改

这篇文章主要针对java初学者&#xff0c;详细介绍怎么创建一个基本的springboot项目来对数据库进行crud操作。 目录 第一步&#xff1a;准备数据库 第二步&#xff1a;创建springboot项目 方法1&#xff1a;通过spring官网的spring initilizer创建springboot项目 方法2&am…

UG NX二次开发(C#)-CAM自定义铣加工的出口环境

文章目录 1、前言2、自定义铣削加工操作3、出错原因4、解决方案4.1 MILL_USER的用户参数4.2 采用自定义铣削的方式生成自定义的dll4.2 配置加工的出口环境4.3 调用dll5、结论1、前言 作为一款大型的CAD/CAM软件, UG NX为我们提供了丰富的加工模板,通过加工模板能直接用于生成…

day7 8-牛客67道剑指offer-JZ74、57、58、73、61、62、64、65、把字符串转换成整数、数组中重复的数字

文章目录 1. JZ74 和为S的连续正数序列暴力解法滑动窗口&#xff08;双指针&#xff09; 2. JZ57 和为S的两个数字3. JZ58 左旋转字符串4. JZ73 翻转单词序列5. JZ61 扑克牌顺子6. JZ62 孩子们的游戏(圆圈中最后剩下的数)迭代 模拟递归 约瑟夫环问题 找规律 7. JZ64 求123...n8…

0基础学C#笔记08:插入排序法

文章目录 前言一、过程简单描述&#xff1a;二、代码总结 前言 我们在玩打牌的时候&#xff0c;你是怎么整理那些牌的呢&#xff1f;一种简单的方法就是一张一张的来&#xff0c;将每一张牌插入到其他已经有序的牌中的适当位置。当我们给无序数组做排序的时候&#xff0c;为了…

SpringBoot 该如何预防 XSS 攻击

XSS 漏洞到底是什么&#xff0c;说实话我讲不太清楚。但是可以通过遇到的现象了解一下。在前端Form表单的输入框中&#xff0c;用户没有正常输入&#xff0c;而是输入了一段代码&#xff1a;</input><img src1 onerroralert1> 这个正常保存没有问题。问题出在了列表…

竞赛项目 深度学习疲劳驾驶检测 opencv python

文章目录 0 前言1 课题背景2 实现目标3 当前市面上疲劳驾驶检测的方法4 相关数据集5 基于头部姿态的驾驶疲劳检测5.1 如何确定疲劳状态5.2 算法步骤5.3 打瞌睡判断 6 基于CNN与SVM的疲劳检测方法6.1 网络结构6.2 疲劳图像分类训练6.3 训练结果 7 最后 0 前言 &#x1f525; 优…

HCIP-linux和kvm(ks配置文件自动化安装及console连虚拟机有问题)

1、linux linux安装教程参考&#xff0c;https://blog.51cto.com/cloudcs/5245337 yum源配置 本地yum源配置&#xff1a; 8版本配置&#xff1a;将光盘iso挂载到某个目录&#xff0c;/dev/cdrom是/dev/sr0软链接&#xff0c;# mount /dev/cdrom /mnt&#xff0c;# ls /mnt Ap…

.NET6使用SqlSugar操作数据库

1.//首先引入SqlSugarCore包 2.//新建SqlsugarSetup类 public static class SqlsugarSetup{public static void AddSqlsugarSetup(this IServiceCollection services, IConfiguration configuration,string dbName "ConnectString"){SqlSugarScope sqlSugar new Sq…

手动创建一个DOCKER镜像

1. 我们先使用C语言写一个hello-world程序 vim hello.c # include <stdio.h>int main() {print("hello docker\n"); } 2. 将hello.c文件编译成二进制文件, 需要安装工具 yum install gcc yum install glibc-static 开始编译 gcc -static hello.c -o hello 编译…

Mybatis Plus条件构造器LambdaQueryWrapper

官网地址 Mybatis Plus条件构造器LambdaQueryWrapper 目前数据库数据情况&#xff0c;User表 iduser_namebirthdaysexaddress1张12023-08-10男123163.com2李12023-08-10女222163.com3张22023-08-10女999163.com4张32023-08-10男9994qq.com ## 简单介绍 如何使用各种场景 方法…

基于Promise.resolve实现Koa请求队列中间件

本文作者为360奇舞团前端工程师 前言 最近在做一个 AIGC 项目&#xff0c;后端基于 Koa2 实现。其中有一个需求就是调用兄弟业务线服务端 AIGC 能力生成图片。但由于目前兄弟业务线的 AIGC 项目也是处于测试阶段&#xff0c;能够提供的服务器资源有限&#xff0c;当并发请求资源…

Java算法_ LRU 缓存(LeetCode_Hot100)

题目描述&#xff1a;请你设计并实现一个满足 LRU &#xff08;最近最少使用&#xff09; 缓存 约束的数据结构。 获得更多&#xff1f;算法思路:代码文档&#xff0c;算法解析的私得。 运行效果 完整代码 import java.util.HashMap; import java.util.Map;/*** 2 * Author: L…

微信小程序备案流程

微信小程序备案流程 &#x1f4d4; 千寻简笔记介绍 千寻简笔记已开源&#xff0c;Gitee与GitHub搜索chihiro-notes&#xff0c;包含笔记源文件.md&#xff0c;以及PDF版本方便阅读&#xff0c;且是用了精美主题&#xff0c;阅读体验更佳&#xff0c;如果文章对你有帮助请帮我…

Oracle database Linux自建环境备份至远端服务器自定义保留天数

环境准备 linux下安装oracle 请看 oracle12c单节点部署 系统版本: CentOS 7 软件版本&#xff1a; Oracle12c 备份策略与实现方法 此次备份依赖Oracle自带命令exp与linux下crontab命令&#xff08;定时任务&#xff09; exp Oracle中exp命令是一个用于导出数据库数据和对象的…

算法竞赛入门【码蹄集新手村600题】(MT1140-1160)C语言

算法竞赛入门【码蹄集新手村600题】(MT1140-1160&#xff09;C语言 目录MT1141 数字3MT1142 整除的总数MT1143 沙哈德数MT1144 整除MT1145 全部整除MT1146 孙子歌诀MT1147 古人的剩余定理MT1148 隐晦余8MT1149 余数MT1150 战死四五百MT1151 韩信生气MT1152 韩信又生气了MT1153 …

UML类图

UML类图 类与类之间的关系 类与类之间的关系 依赖 一个类的对象,作为另一个类的局部变量, 虚线加箭头表示继承 实线三角实现 虚线三角关联 一个类的对象,作为一个类的字段 实线箭头 a. 组合 实心菱形实线箭头 b. 聚合 空心菱形实线箭头