Java 基本数据类型 sizeof 功能

本文详细探讨了Java中基本数据类型的内存占用情况,并通过实验验证了不同封装对象的实际内存使用量。
Java基本数据类型
int 32bit

short 16bit
long 64bit
byte 8bit
char 16bit
float 32bit
double 64bit
boolean 1bit,This data type represents one bit of information, but its "size" isn't something that's precisely defined.(ref

Java基本数据类型大小
	private static void calSize() {
		System.out.println("Integer: " + Integer.SIZE/8);			// 4
		System.out.println("Short: " + Short.SIZE/8);				// 2	
		System.out.println("Long: " + Long.SIZE/8);					// 8
		System.out.println("Byte: " + Byte.SIZE/8);					// 1
		System.out.println("Character: " + Character.SIZE/8);		// 2
		System.out.println("Float: " + Float.SIZE/8);				// 4
		System.out.println("Double: " + Double.SIZE/8);				// 8
//		System.out.println("Boolean: " + Boolean);
	}

Java中模拟c中对sizeof的实现
思路: 利用java中GC内存回收前后的heap size差别,得出每个object的大小


这是一个程序,java中没有现成的sizeof的实现,原因主要是java中的基本数据类型的大小都是固定的,所以看上去没有必要用sizeof这个关键字。
实现的想法是这样的:java.lang.Runtime类中有一些简单的能涉及到内存管理的函数:
Every Java application has a single instance of classRuntimethat allows the application to interface with the environment in which the application is running. The current runtime can be obtained from thegetRuntimemethod.
long
freeMemory()
Returns the amount of free memory in the Java Virtual Machine.
void
gc()
Runs the garbage collector.
static Runtime
getRuntime()
Returns the runtime object associated with the current Java application.
long
maxMemory()
Returns the maximum amount of memory that the Java virtual machine will attempt to use.
void
runFinalization()
Runs the finalization methods of any objects pending finalization.
使用这些简单的内存访问,可以得到内存的一些情况,我们通过建立一个大的某个类的数组,来查看内存用了多少,进而可以求得类的大小。

源码:

	private static void calSize2() {
		runGC();

		long heap1 = 0;
		final int count = 100000;
		Object[] objs = new Object[count];

		for(int i=-1; i<count; i++) {
			Object obj = null;
			obj = new Object();					// 8
//			obj = new Integer( i );				// 16
//			obj = new Short( (short)i );		// 16
//			obj = new Long( i );				// 16
//			obj = new Byte( (byte)0 );			// 16
//			obj = new Character( (char)i );		// 16
//			obj = new Float( i );				// 16
//			obj = new Double( i );				// 16
//			obj = new Boolean( true );			// 16
//			obj = new String();					// 40
			
			
			if(i<0){
				obj = null;
				runGC();
				heap1 = usedMemory();	// before memory size
			} else {
				objs[i] = obj; 
			}
		}

		runGC();
		long heap2 = usedMemory();		// after memory size
		
		final int size = (int)Math.round( (heap2 - heap1)/(double)count );
		System.out.println("heap1 = " + heap1 + "; heap2 = " + heap2);
		System.out.println("heap2-heap1 = " + (heap2 - heap1) + "; " + objs[0].getClass().getSimpleName() + " size = " + size);
		
		for(int i=0; i<count; i++) {
			objs[i] = null;
		}
		objs = null;
		runGC();
	}
	
	private static void runGC() {
		for(int i=0; i<4; i++) {
			long usedMem1 = usedMemory();
			long usedMem2 = Long.MAX_VALUE;
			
			for(int j=0; (usedMem1<usedMem2) && (j<500); j++) {
				rTime.runFinalization();
				rTime.gc();
				Thread.yield();
				
				usedMem2 = usedMem1;
				usedMem1 = usedMemory();
			}
		}
	}
	
	private static long usedMemory() {
		return rTime.totalMemory() - rTime.freeMemory();
	}


注意:Object[] objects = new Object[count];
只是分配了数组空间,没有分配对象的空间。数组中只有引用而已。
结论:下代码测试基本对象时,得出的结果象下面:
Object obj = null;
obj = new Object(); // 8
obj = new Integer( i ); // 16
obj = new Short( (short)i ); // 16
obj = new Long( i ); // 16
obj = new Byte( (byte)0 ); // 16
obj = new Character( (char)i ); // 16
obj = new Float( i ); // 16
obj = new Double( i ); // 16
obj = new Boolean( true ); // 16
obj = new String(); // 40

怎么会这样呢???解释如下:
这个例子写的很好,正好说明了java中基本类型封装对象所占内存的大小.
1.简单的Object对象要占用8个字节的内存空间,因为每个实例都至少必须包含一些最基本操作,比如:wait()/notify(),equals(), hashCode()等
2.使用Integer对象占用了16个字节,而int占用4个字节,说了封装了之后内存消耗大了4倍

3.那么Long看起来比Integer对象应该使用更多空间,结果Long所占的空间也是16个字节.
那么就正好说明了JVM的对于基本类型封装对象的内存分配的规则是如下:
Object所占内存(8个字节)+最大基本类型(long)所占内存(8个字节) = 16字节.
JVM强制使用8个字节作为边界.
所以 所有基本类型封装对象所占内存的大小都是16字节.
但是还是有区别,比如:
Integer对象虽然占用了16个字节的内存,但是只是利用了 Object所占内存(8个字节)+int所占内存(4个字节) = 12字节.
还有4个字节根本没有被使用.呵呵,仔细分析了一晚,还是有很多收获的




参考推荐:
Primitive Data Types(SUN 官方文档)

C:\Users\kiki>ssh root@192.168.10.122 The authenticity of host '192.168.10.122 (192.168.10.122)' can't be established. ED25519 key fingerprint is SHA256:3aSXSmZgEArfV83eQbHRW5adsYXZ/H/JtHC7GuVJqBI. This key is not known by any other names. Are you sure you want to continue connecting (yes/no/[fingerprint])? yes Warning: Permanently added '192.168.10.122' (ED25519) to the list of known hosts. root@192.168.10.122's password: Permission denied, please try again. root@192.168.10.122's password: Welcome to Linaro 14.04 (GNU/Linux 4.14.0-gb6e379910a11-dirty armv7l) * Documentation: https://wiki.analog.com/ https://ez.analog.com/ Last login: Thu Jan 1 00:00:13 1970 root@analog:~# ls openwifi root@analog:~# cd openwifi/ root@analog:~/openwifi# ./wgd.sh usage: Script for load (or download+load) different driver and FPGA img without rebooting no argument: Load .ko driver files and FPGA img (if system_top.bit.bin exist) in current dir with test_mode=0. 1st argument: If it is a NUMBER, it will be assigned to test_mode. Then load everything from current dir. 1st argument: If it is a string called "remote", it will download driver/FPGA and load everything. - 2nd argument (if exist) is the target directory name for downloading and reloading - 3rd argument (if exist) is the value for test_mode 1st argument: neither NUMBER nor "remote" nor a .tar.gz file, it is regarded as a directory and load everything from it. - 2nd argument (if exist) is the value for test_mode 1st argument: a .tar.gz file, it will be unpacked then load from that unpacked directory - 2nd argument (if exist) is the value for test_mode TARGET_DIR ./ DOWNLOAD_FLAG 0 test_mode 0 tx_offset_tuning_enable 0 $TARGET_DIR is found! network-manager stop/waiting rmmod: ERROR: Module sdr is not currently loaded rmmod: ERROR: Module ad9361_drv is not currently loaded + insmod .//ad9361_drv.ko ad9361_drv is loaded! .//system_top.bit.bin not found. Skip reloading FPGA. xlnx,zynq-7000 fjdo349ujtrueugjh
03-26
<think>嗯,用户这次聚焦在SSH访问的"Permission denied, please try again"报错上。从引用内容看,这个问题涉及多个层面的可能性,需要系统性地排查。用户应该是在管理Linux服务器时遇到了访问阻断,情绪可能比较焦虑——毕竟连不上服务器会直接影响工作。 先拆解引用中的有效信息:引用[2]直接关联SSH配置,提到PermitRootLogin和PubkeyAuthentication两个关键参数,还补充了HostKeyAlgorithms这个容易被忽略的算法兼容项;引用[3]则指出账号过期时间这种边缘case。有趣的是引用[1]和[4]虽然都提到Permission denied,但实际是公钥认证和Git权限问题,与当前问题相关性较弱。 用户明确要求解决交互式登录场景的报错(注意报错信息中带"please try again"),这和公钥认证失败报错文本不同。这说明更可能是密码认证或基础配置问题。需要重点检查:1)sshd_config里的密码认证开关 2)PAM模块限制 3)用户账号状态 4)selinux/firewall干扰。 考虑到用户可能是运维人员,在回复里加入具体命令示例会更实用。比如用chage命令检查账号过期时间,用semanage调整selinux策略这些具体操作。不过要注意提醒sudo权限需求,避免用户直接复制命令引发权限错误。 测试环节特别重要,用户可能没有意识到修改配置后需要重启sshd服务。这里要用$$语法强调重启命令的格式,因为CentOS7和Ubuntu22.04的命令不同(systemctl restart sshd vs service ssh restart)。对了,还要提醒测试时保留现有会话,防止配置错误导致完全断开连接。 最后想到个隐藏风险点:如果用户通过跳板机连接,实际报错来源可能是中转服务器。这个在回复里用括号补充说明比较合适,避免用户走弯路。 </think>针对SSH访问失败报错"Permission denied, please try again."的问题,结合引用内容及系统排查逻辑,解决方案如下: ### 一、核心配置检查(优先处理) 1. **启用密码登录** 修改`/etc/ssh/sshd_config`: ```bash sudo vim /etc/ssh/sshd_config ``` 确保以下参数为: ```nginx PasswordAuthentication yes # 允许密码登录 PermitRootLogin yes # 允许root登录(按需开启) PubkeyAuthentication yes # 开启公钥认证[^2] ``` **重启服务**生效: ```bash sudo systemctl restart sshd ``` 2. **密钥算法兼容性**(针对OpenSSH升级问题) 在相同文件末尾添加: ```nginx HostKeyAlgorithms +ssh-rsa # 兼容旧算法[^2] ``` --- ### 二、账户状态排查 1. **检查账户过期时间** ```bash sudo chage -l [用户名] # 查看账户有效期 ``` 若账户过期: ```bash sudo chage -E "2024-12-31" [用户名] # 延长有效期至指定日期[^3] ``` 2. **密码策略验证** ```bash sudo passwd [用户名] # 重置密码(触发密码状态更新) ``` --- ### 三、权限与SELinux 1. **关键目录权限** ```bash sudo chmod 700 ~/.ssh # 用户密钥目录 sudo chmod 600 ~/.ssh/authorized_keys # 公钥文件 ``` 2. **关闭SELinux临时测试** ```bash sudo setenforce 0 # 临时禁用 ``` > 若登录成功,需永久关闭需修改`/etc/selinux/config`中的`SELINUX=disabled` --- ### 四、连接测试与诊断 - **带调试信息连接**: ```bash ssh -vvv user@host # 显示详细错误流 ``` - **检查服务状态**: ```bash sudo systemctl status sshd # 确认服务运行 sudo journalctl -u sshd -n 50 # 查看最近50条日志 ``` ### 五、其他可能原因 - **防火墙拦截**: ```bash sudo ufw allow ssh # Ubuntu sudo firewall-cmd --add-service=ssh --permanent # CentOS ``` - **PAM模块限制**:检查`/etc/pam.d/sshd`是否有限制规则 - **用户Shell配置**:确保`/etc/passwd`中用户shell有效(如`/bin/bash`) > **关键提示**:修改配置后必须重启SSH服务方能生效: > $$ \text{执行命令: } \texttt{sudo systemctl restart sshd} $$
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值