parent
2ded412bae
commit
d8edd99a84
24 changed files with 191 additions and 328 deletions
@ -0,0 +1,166 @@ |
||||
--- |
||||
title: 使用VirtualBox虚拟机安装群晖7.1系统 |
||||
abbrlink: 1751037144 |
||||
date: 2024-04-03 11:10:00 |
||||
tags: |
||||
categories: |
||||
keywords: |
||||
description: |
||||
cover: |
||||
--- |
||||
>VirtualBox为开源软件,较Vmware更加轻量,在此推荐使用VirtualBox来安装群晖系统。 |
||||
>本文主要介绍群晖(DS920+)在VirtualBox虚拟机上的详细安装教程。 |
||||
|
||||
# 下载并安装VirtualBox |
||||
|
||||
到[VirtualBox官网](https://www.virtualbox.org/wiki/Downloads)下载最新版的VirtualBox,安装时如图一路下一步即可。 |
||||
看到如下界面表示安装完成。 |
||||
|
||||
<img src="https://img.dreamlyn.cn:8443/i/2024/04/15/140039.webp"/> |
||||
|
||||
|
||||
|
||||
# 下载群晖引导 |
||||
|
||||
在此给出目前最新版群晖引导的[下载地址](https://oss.dreamlyn.cn/nas/黑群晖/arpl-zh_CN-1.1-beta2a.vmdk-flat.zip)。 |
||||
|
||||
# 添加虚拟机 |
||||
|
||||
如图在系统中找打合适的位置创建NAS目录,解压刚才下载的群晖引导,并将里面的内容拷贝到创建的目录。 |
||||
|
||||
<img src="https://img.dreamlyn.cn:8443/i/2024/04/15/145132.webp"/> |
||||
|
||||
打开VirtualBox,点击`新建`创建虚拟机。 |
||||
|
||||
<img src="https://img.dreamlyn.cn:8443/i/2024/04/15/145519.webp"/> |
||||
|
||||
如图,名字随便起,文件夹选择刚才创建的文件夹,类型选Linux,版本选Other Linux(64-bit) |
||||
|
||||
<img src="https://img.dreamlyn.cn:8443/i/2024/04/15/150006.webp"/> |
||||
|
||||
硬件部分按需选择,这里我内存设置4G,cpu4核。 |
||||
|
||||
<img src="https://img.dreamlyn.cn:8443/i/2024/04/15/150315.webp"/> |
||||
|
||||
虚拟硬盘处选择使用已有的虚拟硬盘文件。 |
||||
|
||||
<img src="https://img.dreamlyn.cn:8443/i/2024/04/15/150742.webp"/> |
||||
|
||||
在弹出的框中点击注册 |
||||
|
||||
<img src="https://img.dreamlyn.cn:8443/i/2024/04/15/151415.webp"/> |
||||
|
||||
随后找到先前创建的目录并选择`arpl.vmdk` |
||||
|
||||
<img src="https://img.dreamlyn.cn:8443/i/2024/04/15/151120.webp"/> |
||||
|
||||
点击完成 |
||||
|
||||
<img src="https://img.dreamlyn.cn:8443/i/2024/04/15/151515.webp"/> |
||||
|
||||
随后再对虚拟机进行配置,点击设置。 |
||||
|
||||
<img src="https://img.dreamlyn.cn:8443/i/2024/04/15/152313.webp"/> |
||||
|
||||
选择存储后,点击添加虚拟硬盘,这块新加的虚拟硬盘是真正安装存储群晖系统的地方,应适当大一些。 |
||||
|
||||
<img src="https://img.dreamlyn.cn:8443/i/2024/04/15/153746.webp"/> |
||||
|
||||
点击创建,选择VDI(VirtualBox磁盘映像)并点击下一步。 |
||||
|
||||
<img src="https://img.dreamlyn.cn:8443/i/2024/04/15/152701.webp"/> |
||||
|
||||
点击下一步 |
||||
|
||||
<img src="https://img.dreamlyn.cn:8443/i/2024/04/15/152838.webp"/> |
||||
|
||||
设置磁盘大小并点击完成。 |
||||
|
||||
<img src="https://img.dreamlyn.cn:8443/i/2024/04/15/152924.webp"/> |
||||
|
||||
选中刚才创建的磁盘并点击选择。 |
||||
|
||||
<img src="https://img.dreamlyn.cn:8443/i/2024/04/15/153109.webp"/> |
||||
|
||||
|
||||
点击网络,将网络连接设置成桥接模式。 |
||||
|
||||
<img src="https://img.dreamlyn.cn:8443/i/2024/04/15/154720.webp"/> |
||||
|
||||
随后点击确定并在主界面点击启动 |
||||
|
||||
<img src="https://img.dreamlyn.cn:8443/i/2024/04/15/153324.webp"/> |
||||
|
||||
# 配置并启动引导 |
||||
|
||||
点击启动后,稍等片刻,在如下界面按下回车键开始对引导进行配置。 |
||||
|
||||
<img src="https://img.dreamlyn.cn:8443/i/2024/04/15/155113.webp"/> |
||||
|
||||
看到如下配置后,说明引导已正常启动。 |
||||
|
||||
<img src="https://img.dreamlyn.cn:8443/i/2024/04/15/155426.webp"/> |
||||
|
||||
我们在浏览器中输入红框框出来的地址,`192.168.31.119:7681`进入如下界面。 |
||||
|
||||
<img src="https://img.dreamlyn.cn:8443/i/2024/04/15/155643.webp"/> |
||||
|
||||
选中选择型号并回车,在转到的界面中选择DS920+ |
||||
|
||||
<img src="https://img.dreamlyn.cn:8443/i/2024/04/15/155737.webp"/> |
||||
|
||||
随后选择版本,这里选择42661 |
||||
|
||||
<img src="https://img.dreamlyn.cn:8443/i/2024/04/15/163532.webp"/> |
||||
|
||||
选择SN码,直接选择生成随机SN。 |
||||
|
||||
<img src="https://img.dreamlyn.cn:8443/i/2024/04/15/160435.webp"/> |
||||
|
||||
在插件中选择添加插件并添加`cpuinfo`插件 |
||||
|
||||
<img src="https://img.dreamlyn.cn:8443/i/2024/04/15/160047.webp"/> |
||||
|
||||
插件的加载参数为空,确认 |
||||
|
||||
<img src="https://img.dreamlyn.cn:8443/i/2024/04/15/160126.webp"/> |
||||
|
||||
随后直接选中编译引导并回车,待编译完成后选中启动并回车。 |
||||
|
||||
<img src="https://img.dreamlyn.cn:8443/i/2024/04/15/163703.webp"/> |
||||
|
||||
# 安装群晖系统 |
||||
|
||||
下载群晖助手并安装启动,[下载地址](https://template-mine.oss-cn-beijing.aliyuncs.com/nas/blog/synology-assistant-7.0.3-50049.exe) |
||||
|
||||
如图,扫描群晖系统(期间可能需要关闭防火墙)。 |
||||
|
||||
<img src="https://img.dreamlyn.cn:8443/i/2024/04/15/164132.webp"/> |
||||
|
||||
找到DSM未安装的那个就是刚才用虚拟机安装的NAS,我们用浏览器访问对应的IP地址`http://192.168.31.119:5000/`进入如下界面,点击安装。 |
||||
|
||||
<img src="https://img.dreamlyn.cn:8443/i/2024/04/15/164336.webp"/> |
||||
|
||||
从以下链接下载DSM系统 |
||||
|
||||
``` |
||||
https://global.synologydownload.com/download/DSM/release/7.1/42661-1/DSM_DS920%2B_42661.pat |
||||
``` |
||||
|
||||
点击浏览,并选择刚才下载的DSM系统,点击下一步。 |
||||
|
||||
<img src="https://img.dreamlyn.cn:8443/i/2024/04/15/164819.webp"/> |
||||
|
||||
点继续。 |
||||
|
||||
<img src="https://img.dreamlyn.cn:8443/i/2024/04/15/164847.webp"/> |
||||
|
||||
随后进入安装界面,待进度走到100%后,我们就完成了虚拟机中群晖系统的安装。 |
||||
|
||||
<img src="https://img.dreamlyn.cn:8443/i/2024/04/15/164954.webp"/> |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -1,37 +0,0 @@ |
||||
--- |
||||
title: MySQL索引设计原则 |
||||
tags: Java技术 |
||||
categories: 技术随笔 |
||||
abbrlink: 167789376 |
||||
date: 2024-03-14 16:40:20 |
||||
keywords: |
||||
description: |
||||
cover: |
||||
--- |
||||
|
||||
# 代码先行,索引后上 |
||||
一般应该等到主体业务功能开发完毕,把涉及到该表相关sql都要拿出来分析之后再建立索引。 |
||||
|
||||
# 联合索引尽量覆盖条件 |
||||
设计一个或者两三个联合索引(尽量少建单值索引),让每一个联合索引都尽量去包含sql语句里的where、order by、group by的字段,还要确保这些联合索引的字段顺序尽量满足sql查询的最左前缀原 则。 |
||||
|
||||
# 不要在小基数字段上建立索引 |
||||
索引基数是指这个字段在表里总共有多少个不同的值,比如一张表总共100万行记录,其中有个性别字段, 其值不是男就是女,那么该字段的基数就是2。 |
||||
如果对这种小基数字段建立索引的话,还不如全表扫描了,因为你的索引树里就包含男和女两种值,根本没法进行快速的二分查找,那用索引就没有太大的意义了。 |
||||
一般建立索引,尽量使用那些基数比较大的字段,就是值比较多的字段,那么才能发挥出B+树快速二分查找的优势来。 |
||||
|
||||
# 长字符串我们可以采用前缀索引 |
||||
尽量对字段类型较小的列设计索引,比如说什么tinyint之类的,因为字段类型较小的话,占用磁盘空间也会比较小,此时你在搜索的时候性能也会比较好一点。 |
||||
当然,这个所谓的字段类型小一点的列,也不是绝对的,很多时候你就是要针对varchar(255)这种字段建立索引,哪怕多占用一些磁盘空间也是有必要的。 |
||||
对于这种varchar(255)的大字段可能会比较占用磁盘空间,可以稍微优化下,比如针对这个字段的前20个字符建立索引,就是说,对这个字段里的每个值的前20个字符放在索引树里, |
||||
类似于 KEY index(name(20),age,position)。此时你在where条件里搜索的时候,如果是根据name字段来搜索,那么此时就会先到索引树里根据name |
||||
字段的前20个字符去搜索,定位到之后前20个字符的前缀匹配的部分数据之后,再回到聚簇索引提取出来完整的name字段值进行比对。 |
||||
但是假如你要是order by name,那么此时你的name因为在索引树里仅仅包含了前20个字符,所以这个排序是没法用上索引的, group by也是同理。所以这里大家要对前缀索引有一个了解。 |
||||
|
||||
# where与order by冲突时优先where |
||||
在where和order by出现索引设计冲突时,到底是针对where去设计索引,还是针对order by设计索引?到底是让where去用上索引,还是让order by用上索引? |
||||
一般这种时候往往都是让where条件去使用索引来快速筛选出来一部分指定的数据,接着再进行排序。 |
||||
因为大多数情况基于索引进行where筛选往往可以最快速度筛选出你要的少部分数据,然后做排序的成本可能会小很多。 |
||||
|
||||
# 基于慢sql查询做优化 |
||||
可以根据监控后台的一些慢sql,针对这些慢sql查询做特定的索引优化。 |
@ -1,138 +0,0 @@ |
||||
--- |
||||
title: java中的类加载器 |
||||
tags: Java技术 |
||||
categories: 技术随笔 |
||||
abbrlink: 3639892104 |
||||
date: 2024-03-06 16:22:05 |
||||
keywords: |
||||
description: |
||||
cover: |
||||
--- |
||||
> java中的类加载器主要有三种: |
||||
> 引导类加载器 |
||||
> 扩展类加载器 |
||||
> 应用类加载器 |
||||
|
||||
# 通过代码了解类加载器 |
||||
|
||||
``` |
||||
public class TestJDKClassLoader { |
||||
public static void main(String[] args) { |
||||
//打印类加载器 |
||||
System.out.println(String.class.getClassLoader()); //不是java对象,打印null |
||||
System.out.println(DESKeyFactory.class.getClassLoader()); |
||||
System.out.println(TestJDKClassLoader.class.getClassLoader()); |
||||
//类加载器之间的关系 |
||||
System.out.println(); |
||||
ClassLoader appClassLoader = ClassLoader.getSystemClassLoader(); |
||||
ClassLoader extClassLoader = appClassLoader.getParent(); |
||||
ClassLoader bootstrapLoader = extClassLoader.getParent(); |
||||
System.out.println(appClassLoader); |
||||
System.out.println(extClassLoader); |
||||
System.out.println(bootstrapLoader); |
||||
|
||||
System.out.println(); |
||||
System.out.println("bootstrapLoader加载以下文件:"); |
||||
URL[] urLs = Launcher.getBootstrapClassPath().getURLs(); |
||||
for (URL url : urLs) { |
||||
System.out.println(url); |
||||
} |
||||
|
||||
System.out.println(); |
||||
System.out.println("extClassLoader加载以下文件:"); |
||||
System.out.println(System.getProperty("java.ext.dirs")); |
||||
|
||||
System.out.println(); |
||||
System.out.println("appClassLoader加载以下文件"); |
||||
System.out.println(System.getProperty("java.class.path")); |
||||
|
||||
} |
||||
} |
||||
``` |
||||
|
||||
# 双亲委派机制 |
||||
|
||||
JVM在进行类加载时有个双亲委派机制,当它需要去加载类时,自己先不去加载,而是委托给父加载器加载,父加载器又直接委派它的父加载器,直到找到引导类加载器时,他才会去对类进行加载,这时候如果加载不到,也就是在它所管辖的范围内找不到这个类,就会进行委托的退回,说,啊,我不行,还是你自己来吧,这样一直退回到能加载这个类的时候,才会对类进行加载。 |
||||
总结起来就是所有类都会优先使用最顶层的类加载器去加载,从而保证了系统的安全性和类加载的唯一性。 |
||||
比如我是一个黑客,在用户的系统里写了一个String类,这个类里面做了一些危害系统的代码,这时候双亲委派机制就能有效的避过这个类,他是应用类加载器要加载String时,会委派给上层,上层在委派给上上层,一直到引导类加载器,引导类加载器会直接使用Java自带的String类。 |
||||
|
||||
# 全盘负责委托机制 |
||||
|
||||
“全盘负责”是指当一个ClassLoder装载一个类时,除非显式的使用另外一个ClassLoder,否则该类所依赖及引用的类也由这个ClassLoder载入 |
||||
|
||||
# 自定义类加载器 |
||||
|
||||
自定义类加载器只需要继承`java.lang.ClassLoader`类,该类有两个核心方法,一个是`loadClass(String, boolean)`,实现了双亲委派机制,还有一个方法是`findClass`,默认实现是空方法,所以我们自定义类加载器主要是重写`findClass`方法. |
||||
打破双亲委派机制主要就是通过重写`loadClass`方法,去掉它的递归委派的代码。 |
||||
|
||||
测试代码 |
||||
|
||||
``` |
||||
public class MyClassLoaderTest { |
||||
static class MyClassLoader extends ClassLoader { |
||||
private String classPath; |
||||
public MyClassLoader(String classPath) { |
||||
this.classPath = classPath; |
||||
} |
||||
private byte[] loadByte(String name) throws Exception { |
||||
name = name.replaceAll("\\.", "/"); |
||||
FileInputStream fis = new FileInputStream(classPath + "/" + name + ".class"); |
||||
int len = fis.available(); |
||||
byte[] data = new byte[len]; |
||||
fis.read(data); |
||||
fis.close(); |
||||
return data; |
||||
} |
||||
protected Class<?> findClass(String name) throws ClassNotFoundException { |
||||
try { |
||||
byte[] data = loadByte(name); |
||||
// defineClass 将一个字节数组转为 Class 对象, |
||||
// 这个字节数组是 class 文件读取后最终的字节数组 |
||||
return defineClass(name, data, 0, data.length); |
||||
} catch (Exception e) { |
||||
e.printStackTrace(); |
||||
throw new ClassNotFoundException(); |
||||
} |
||||
} |
||||
//双亲委派机制 |
||||
//沙箱安全机制:自己写的java.lang.String.class类不会被加载,这样可以防止核心API库被随意篡改 |
||||
//避免类的重复加载:当父亲已经加载了该类时,就没必要子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) { |
||||
if (!name.startsWith("com.locaris")) { |
||||
c = this.getParent().loadClass(name); |
||||
} else { |
||||
c = findClass(name); |
||||
} |
||||
sun.misc.PerfCounter.getFindClasses().increment(); |
||||
} |
||||
if (resolve) { |
||||
resolveClass(c); |
||||
} |
||||
return c; |
||||
} |
||||
|
||||
} |
||||
} |
||||
public static void main(String args[]) throws Exception { |
||||
// 初始化自定义类加载器,会初始化父类 ClassLoader |
||||
// 其中会把自定义类加载器的父类加载器,设置为应用程序类加载器 AppClassLoader |
||||
MyClassLoader classLoader = new MyClassLoader("D:/test"); |
||||
// D 盘创建 test/com/swordsman/jvm 几级目录,将 User 类的复制类 User1 丢入该目录 |
||||
Class clazz = classLoader.loadClass("com.youren.jvm.User"); |
||||
Object obj = clazz.newInstance(); |
||||
Method method = clazz.getDeclaredMethod("sout", null); |
||||
method.invoke(obj, null); |
||||
|
||||
// 这里因为双亲委派机制的原因, |
||||
// 如果 User1 也在 classpath 下,类加载器就是 AppClassLoader |
||||
// 只在 D:/test 下就是自定义加载器 |
||||
System.out.println(clazz.getClassLoader().getClass().getName()); |
||||
} |
||||
} |
||||
``` |
@ -1,31 +0,0 @@ |
||||
--- |
||||
title: java程序启动时都发生了什么 |
||||
tags: Java技术 |
||||
categories: 技术随笔 |
||||
abbrlink: 1818557386 |
||||
date: 2024-03-06 14:22:05 |
||||
keywords: |
||||
description: |
||||
cover: |
||||
--- |
||||
|
||||
> 本文主要介绍在我们执行java -jar xxx.jar时都发生了什么,附框图。 |
||||
|
||||
当我们执行这个命令时: |
||||
1. java命令会去调用jvm.dll来创建java虚拟机 |
||||
2. java虚拟机创建一个引导类加载器,并使用它加载sun.misc.Launcher类 |
||||
3. Launcher类创建一些其他的类加载器,比如appclassloader,随后appclassloader会去加载Main.class类。 其中main class是从jar包中的MANIFEST.MF文件找到的。 |
||||
|
||||
<img src="https://img.dreamlyn.cn:8443/i/2024/03/06/142407.webp" width="100%" height="50%"> |
||||
|
||||
加载的过程如下: |
||||
1. 首先把类从硬盘加载到jvm内存,具体是在方法区 |
||||
2. 然后对类进行验证,主要是验证这个类的字节码是否符合Java的规范,比如某个字节放Java的主版本,次版本,某个字节放类的常量个数等。 |
||||
3. 之后进行准备,主要是对类内的静态变量分配内存并赋予默认值. |
||||
4. 随后进行解析,把类内部的符号变量替换为一些静态地址. |
||||
5. 最后进行初始化,对静态变量赋予初始值。 |
||||
|
||||
<img src="https://img.dreamlyn.cn:8443/i/2024/03/06/142424.webp" width="100%" height="50%"> |
||||
|
||||
> 个人理解: |
||||
> 类加载过程就是读取.class文件到内存中,将其放在方法区内,然后在Java堆区创建一个java.lang.Class对象,通过Class对象来访问方法区中类的数据结构。类加载的最终产品是位于堆区中的Class对象,Class对象封装了类在方法区内的数据结构,并且向Java程序员提供了访问方法区内的数据结构的接口。 |
@ -1,97 +0,0 @@ |
||||
--- |
||||
title: 使用jolcore库查看Java对象大小 |
||||
tags: Java技术 |
||||
categories: 技术随笔 |
||||
abbrlink: 155251202 |
||||
date: 2024-03-011 14:22:05 |
||||
keywords: |
||||
description: |
||||
cover: |
||||
--- |
||||
|
||||
> 对象大小可以用jolcore包查看,本篇介绍jolcore的基本使用 |
||||
|
||||
|
||||
# 引入依赖 |
||||
|
||||
``` |
||||
<dependency> |
||||
<groupId>org.openjdk.jol</groupId> |
||||
<artifactId>jol-core</artifactId> |
||||
<version>0.9</version> |
||||
</dependency> |
||||
``` |
||||
# 具体使用 |
||||
``` |
||||
ClassLayout layout = ClassLayout.parseInstance(new Object()); |
||||
System.out.println(layout.toPrintable()); |
||||
``` |
||||
|
||||
# 测试代码 |
||||
``` |
||||
import org.openjdk.jol.info.ClassLayout; |
||||
public class JOLSample { |
||||
public static void main(String[] args) { |
||||
ClassLayout layout = ClassLayout.parseInstance(new Object()); |
||||
System.out.println(layout.toPrintable()); |
||||
System.out.println(); |
||||
ClassLayout layout1 = ClassLayout.parseInstance(new int[]{1,2,3,4,5}); |
||||
System.out.println(layout1.toPrintable()); |
||||
System.out.println(); |
||||
ClassLayout layout2 = ClassLayout.parseInstance(new A()); |
||||
System.out.println(layout2.toPrintable()); |
||||
} |
||||
// -XX:+UseCompressedOops 默认开启的压缩所有指针 |
||||
// -XX:+UseCompressedClassPointers 默认开启的只压缩对象头里的类型指针Klass Pointer |
||||
// Oops:Ordinary Object Pointers |
||||
//堆内存大于32G时,指针压缩会失效。 |
||||
//堆内存小于4G时,不需要启用指针压缩,jvm会直接去除高32位地址。 |
||||
public static class A { |
||||
//8B mark word |
||||
//4B Klass Pointer |
||||
int id = 6; //4B |
||||
String name; //4B |
||||
byte b; //1B |
||||
Object o; //4B |
||||
} |
||||
} |
||||
``` |
||||
# 打印结果 |
||||
|
||||
``` |
||||
java.lang.Object object internals: |
||||
OFFSET SIZE TYPE DESCRIPTION VALUE |
||||
0 4 (object header) 01 00 00 00 (00000001 00000000 00000000 00000000) (1) |
||||
4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0) |
||||
8 4 (object header) 00 1c 2f c5 (00000000 00011100 00101111 11000101) (-986768384) |
||||
12 4 (object header) 9a 02 00 00 (10011010 00000010 00000000 00000000) (666) |
||||
Instance size: 16 bytes |
||||
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total |
||||
|
||||
[I object internals: |
||||
OFFSET SIZE TYPE DESCRIPTION VALUE |
||||
0 4 (object header) 01 00 00 00 (00000001 00000000 00000000 00000000) (1) |
||||
4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0) |
||||
8 4 (object header) 68 0b 2f c5 (01101000 00001011 00101111 11000101) (-986772632) |
||||
12 4 (object header) 9a 02 00 00 (10011010 00000010 00000000 00000000) (666) |
||||
16 4 (object header) 05 00 00 00 (00000101 00000000 00000000 00000000) (5) |
||||
20 4 (alignment/padding gap) |
||||
24 20 int [I.<elements> N/A |
||||
44 4 (loss due to the next object alignment) |
||||
Instance size: 48 bytes |
||||
Space losses: 4 bytes internal + 4 bytes external = 8 bytes total |
||||
|
||||
com.locaris.jvm.JOLSample$A object internals: |
||||
OFFSET SIZE TYPE DESCRIPTION VALUE |
||||
0 4 (object header) 01 00 00 00 (00000001 00000000 00000000 00000000) (1) |
||||
4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0) |
||||
8 4 (object header) 10 f6 9c c5 (00010000 11110110 10011100 11000101) (-979569136) |
||||
12 4 (object header) 9a 02 00 00 (10011010 00000010 00000000 00000000) (666) |
||||
16 4 int A.id 6 |
||||
20 1 byte A.b 0 |
||||
21 3 (alignment/padding gap) |
||||
24 8 java.lang.String A.name null |
||||
32 8 java.lang.Object A.o null |
||||
Instance size: 40 bytes |
||||
Space losses: 3 bytes internal + 0 bytes external = 3 bytes total |
||||
``` |
Loading…
Reference in new issue