引用类型 基本类型

引用类型 基本类型 在Java性能优化系列中,内存管理是一个要优先考虑的关键因素。而说到内存分配,就必然会涉及到基本类型和引用类型。所以我们今天就先来介绍一下这两种类型在性能方面各自有什么奥妙。 名词定义 先明确一下什么是基本类型,什么是引用类型。简单地说,所谓基本类型就是Java语言中如下的8种内置类型: boolean、char、byte、short、int、long、float、double。而引用类型就是那些可以通过new来创建对象的类型 (基本上都是派生自Object) 。 ★两种类型的存储方式 这两种类型的差异,首先体现在存储方式上。在Java中,引用类型是存储在堆 (Heap) 上的;而基本类型是存储在栈 (Stack) 上。可能有同学会小声问: 堆和栈有啥区别捏?要说堆和栈的差别,那可就大了去了。如果你对这两个概念还是不太明白或者经常混淆,建议先找本操作系统的书拜读一下。 ★堆和栈的性能差异 堆和栈在性能方面是有很大差别滴。堆相对进程来说是全局的,能够被所有线程访问;而栈是线程局部的,只能本线程访问。打个比方,栈就好比个人小金库,堆就好比国库。你从个人小金库拿钱去花,不需要办什么手续,拿了就花,但是钱数有限;而国库里面的钱虽然很多,但是每次申请花钱要打报告、盖图章、办N多手续,耗时又费力。 同样道理,由于堆是所有线程共有的,从堆里面申请内存要进行相关的加锁操作,因此申请堆内存的复杂度和时间开销比栈要大很多;从栈里面申请内存,虽然又简单又快,但是栈的大小有限,分配不了太多内存。 ★为什么这样设计? 可能有同学又问了,干嘛把两种类型分开存储,干嘛不放到一起捏?这个问题问得好!下面我们就来揣测一下,当初Java为啥设计成这样。 当年Java它爹 (James Gosling) 设计语言的时候,对于这个问题有点进退两难。如果把各种东西都放置到栈中,显然不现实,一来栈是线程私有的 (不便于共享) ,二来栈的大小是有限的,三来栈的结构也间接限制了它的用途。那为啥不把各种东西都放置到堆里面捏?都放堆里面,倒是能绕过上述问题,但是刚才也提到了,申请堆内存要办很多手续,太繁琐。如果仅仅在函数中写一个简单的"int n = 0",也要到堆里面去分配内存,那性能就大大滴差了 (要知道Java是1995年生出来的,那年头我家的PC配4兆内存就属豪华配置了) 。 左思右想之后,Java它爹只好做了一个折中: 把类型分为基本类型和引用类型;引用类型 (Object派生) 的对象存放到堆里面;把基本类型 (非Object派生) 的值存放到栈里面。所以,你从Java语法上也可以看出两者的差别: 引用类型可以用new创建对象 (对于某些单键,表面上没用new,但是在getInstance()内部也还是用的new) ;而基本类型则不需要用new来创建。 这样设计的弊端 顺便跑题一下,斗胆评价Java它爹这种设计的弊端 (希望Java Fans不要跟我急) 。我个人认为: 这个折中的决策,带来了许多深远的影响,随手举出几个例子: 由于基本类型不是派生自Object,因此不能算是纯种的对象。这导致了Java的"纯面向对象"招牌打了折扣。 由于基本类型不是派生自Object,出于某些场合 (比如容器类) 的考虑,不得不为每个基本类型加上对应的包装类 (比如Integer、Byte等) ,使得语言变得有点冗余。 结论 从上述的介绍,我们应该明白,使用new创建对象的开销是不小的。在程序中能避免就应该尽量避免。另外,使用new创建对象,不光是创建时开销大,将来垃圾回收时,销毁对象也是有开销的。 http://program-think.blogspot.com/2009/03/java-performance-tuning-1-two-types.html http://www.ibm.com/developerworks/cn/java/praxis/pr8.html 下表列出了原始类型以及它们的对象封装类。 原始类型和封装类 原始类型 封装类 boolean Boolean char Character byte Byte short Short int Integer long Long float Float double Double 引用类型和原始类型的行为完全不同,并且它们具有不同的语义。例如,假定一个方法中有两个局部变量,一个变量为 int 原始类型,另一个变量是对一个 Integer 对象的对象引用: ...

2012-09-20 · 2 min · 247 words · -

网关

网关 网关(Gateway)又称网间连接器、协议转换器。网关在传输层上以实现网络互连,是最复杂的网络互连设备,仅用于两个高层协议不同的网络互连。网关既可以用于广域网互连,也可以用于局域网互连。 网关是一种充当转换重任的计算机系统或设备。在使用不同的通信协议、数据格式或语言,甚至体系结构完全不同的两种系统之间,网关是一个翻译器。与网桥只是简单地传达信息不同,网关对收到的信息要重新打包,以适应目的系统的需求。同时,网关也可以提供过滤和安全功能。大多数网关运行在OSI 7层协议的顶层-应用层。基本概念 大家都知道,从一个房间走到另一个房间,必然要经过一扇门。同样,从一个网络向另一个网络发送信 网关息,也必须经过一道"关口",这道关口就是网关。顾名思义,网关 (Gateway) 就是一个网络连接到另一个网络的"关口"。也就是网络关卡。 在OSI中,网关有两种: 一种是面向连接的网关,一种是无连接的网关。当两个子网之间有一定距离时,往往将一个网关分成两半,中间用一条链路连接起来,我们称之为半网关。 按照不同的分类标准,网关也有很多种。TCP/IP协议里的网关是最常用的,在这里我们所讲的"网关"均指TCP/IP协议下的网关。 那么网关到底是什么呢?网关实质上是一个网络通向其他网络的IP地址。比如有网络A和网络B,网络A的IP地址范围为"192.168.1.1192. 168.1.254",子网掩码为255.255.255.0;网络B的IP地址范围为"192.168.2.1192.168.2.254",子网掩码为255.255.255.0。在没有路由器的情况下,两个网络之间是不能进行TCP/IP通信的,即使是两个网络连接在同一台交换机 (或集线器) 上,TCP/IP协议也会根据子网掩码 (255.255.255.0) 判定两个网络中的主机处在不同的网络里。而要实现这两个网络之间的通信,则必须通过网关。如果网络A中的主机发现数据包的目的主机不在本地网络中,就把数据包转发给它自己的网关,再由网关转发给网络B的网关,网络B的网关再转发给网络B的某个主机 (如附图所示) 。网络A向网络B转发数据包的过程。 所以说,只有设置好网关的IP地址,TCP/IP协议才能实现不同网络之间的相互通信。那么这个IP地址是哪台机器的IP地址呢?网关的IP地址是具有路由功能的设备的IP地址,具有路由功能的设备有路由器、启用了路由协议的服务器 (实质上相当于一台路由器) 、代理服务器 (也相当于一台路由器) 。 在和 Novell NetWare 网络交互操作的上下文中,网关在 Windows 网络中使用的服务器信息块 (SMB) 协议以及NetWare网络使用的 NetWare 核心协议 (NCP) 之间起着桥梁的作用。网关也被称为 IP 路由器。 举例说明 假设你的名字叫小不点(很小),你住在一个大院子里,你的邻居有很多小伙伴,父母是你的网关。当你想跟院子里的某个小伙伴玩,只要你在院子里大喊一声他的名字,他听到了就会回应你,并且跑出来跟你玩。 但是你家长不允许你走出大门,你想与外界发生的一切联系,都必须由父母 (网关) 用电话帮助你联系。假如你想找你的同学小明聊天,小明家住在很远的另外一个院子里,他家里也有父母 (小明的网关) 。但是你不知道小明家的电话号码,不过你的班主任老师有一份你们班全体同学的名单和电话号码对照表,你的老师就是你的DNS服务器。于是你在家里和父母有了下面的对话: 小不点: 妈妈(或爸爸),我想找班主任查一下小明的电话号码行吗? 网关例子家长: 好,你等着。 (接着你家长给你的班主任挂了一个电话,问清楚了小明的电话) 问到了,他家的号码是211.99.99.99 小不点: 太好了!妈(或爸),我想找小明,你再帮我联系一下小明吧。 家长: 没问题。 (接着家长向电话局发出了请求接通小明家电话的请求,最后一关当然是被转接到了小明家家长那里,然后他家长把电话给转到小明) . 就这样你和小明取得了联系。如果搞清了什么是网关,默认网关也就好理解了。就好像一个房间可以有多扇门一样,一台主机可以有多个网关。默认网关的意思是一台主机如果找不到可用的网关,就把数据包发给默认指定的网关,由这个网关来处理数据包。现在主机使用的网关,一般指的是默认网关。默认网关一般填写192.168.x.1

2012-09-20 · 1 min · 58 words · -

使用 arpalert 来做被动式arp防火墙

使用 arpalert 来做被动式arp防火墙 http://forum.ubuntu.org.cn/viewtopic.php?f=116&t=110347&sid=ae4c75fe6a8b5aa1672e8a05bc6f7d85 我说的被动式是指在探测到欺骗时做出防护动作 在局域网环境中 arp 欺骗是个很头疼的问题, 尤其是网关不是自己控制的时候. 虽然自己可以绑定网关, 但是网关就没办法了. 结果导致网关的东西传不回来, 无法上网. 原理: arpalert 监听网卡收到的 arp 包, 并根据规则(黑白名单等)调用一个防护脚本. 安装: 安装以下包: libnet-arp-perl arpalert(建议用最新的 2.0.11 版, 2.0.10 前的版本处理名单时有问题) 另外将以下文本存为 /usr/local/sbin/arpdef.pl 加上可执行权限(755) [perl] #!/usr/bin/perl -w use strict; if ( $< ) { print “$0n”; system(“sudo”,($0,@ARGV)); exit; } my $mac = $ARGV[0]; my $ip = $ARGV[1]; my ($gateip,$gatemac) = (“192.168.6.1”,“00:04:80:FA:3C:00”); exit 0 if ((“U$mac” eq “U$gatemac”) && ($ip eq $gateip)); #logging .. my $date=`date +"%F %T"`; ...

2012-09-19 · 5 min · 1059 words · -

子网, 子网掩码

子网, 子网掩码 子网掩码 subnet mask 子网掩码只有一个作用,就是将某个IP地址划分成网络地址和主机地址两部分。 https://www.zhihu.com/question/21064101 IP和子网掩码 IP 是由四段数字组成 3 类常用的 IP A 类IP段 0.0.0.0 到 127.255.255.255 B 类IP段 128.0.0.0 到 191.255.255.255 C 类IP段 192.0.0.0 到 223.255.255.255 A 类的默认子网掩码 255.0.0.0 一个子网最多可以容纳 1677 万个 IP B 类的默认子网掩码 255.255.0.0 一个子网最多可以容纳 6 万个 IP C 类的默认子网掩码 255.255.255.0 一个子网最多可以容纳 254 个 IP 要想在同一网段,只要网络标识相同就可以了,那要怎么看网络标识呢?首先要做的是把每段的IP转换为二进制。 (有人说,我不会转换耶,没关系,我们用 windows 自带计算器就行。打开计算器,点查看>科学型,输入十进制的数字,再点一下"二进制"这个单选点,就可以切换至二进制了。) 把子网掩码切换至二进制,我们会发现,所有的子网掩码是由一串连续的1和一串连续的0组成的 (一共4段,每段8位,一共32位数) 。 255.0.0.0 11111111.00000000.00000000.00000000 255.255.0.0 11111111.11111111.00000000.00000000 255.255.255.0 11111111.11111111.11111111.00000000 这是A/B/C三类默认子网掩码的二进制形式,其实,还有好多种子网掩码,只要是一串连续的1和一串连续的0就可以了 (每段都是8位) 。如11111111.11111111.11111000.00000000,这也是一段合法的子网掩码。子网掩码决定的是一个子网的计算机数目,计算机公式是2的m次方,其中,我们可以把m看到是后面的多少颗0。如255.255.255.0 转换成二进制,那就是11111111.11111111.11111111.00000000,后面有8个0,那m就是8,255.255.255.0 这个子网掩码可以容纳2的8次方 (台) 电脑,也就是256台,但是有两个IP是不能用的,那就是最后一段不能为0和255,减去这两台,就是254台。我们再来做一个。 255.255.248.0这个子网掩码可以最多容纳多少台电脑? 计算方法: 把将其转换为二进制的四段数字 (每段要是8位,如果是0,可以写成8个0,也就是00000000) 11111111.1111111.11111000.00000000 然后,数数后面有几颗0,一共是有11颗,那就是2的11次方,等于2048,这个子网掩码最多可以容纳2048台电脑。 一个子网最多可以容纳多少台电脑你会算了吧,下面我们来个逆向算法的题。 一个公司有530台电脑,组成一个对等局域网,子网掩码设多少最合适? 首先,无疑,530台电脑用B类IP最合适 (A类不用说了,太多,C类又不够,肯定是B类) ,但是B类默认的子网掩码是255.255.0.0,可以容纳6万台电脑,显然不太合适,那子网掩码设多少合适呢?我们先来列个公式。 2的m次方=560 首先,我们确定2一定是大于8次方的,因为我们知道2的8次方是256,也就是C类IP的最大容纳电脑的数目,我们从9次方一个一个试2的9次方是512,不到560,2的10次方是1024,看来2的10次方最合适了。子网掩码一共由32位组成,已确定后面10位是0了,那前面的22位就是1,最合适的子网掩码就是: 11111111.11111111.11111100.00000000,转换成10进制,那就是255.255.252.0。 ...

2012-09-19 · 1 min · 133 words · -

JVM 操作数栈 Operand Stack

JVM 操作数栈 Operand Stack http://denverj.iteye.com/blog/1218359 Like the local variables, the operand stack is organized as an array of words. But unlike the local variables, which are accessed via array indices, the operand stack is accessed by pushing and popping values. If an instruction pushes a value onto the operand stack, a later instruction can pop and use that value. 和局部变量区一样,操作数栈也是被组织成一个以字长为单位的数组。但是和前者不同的是,它不是通过索引来访问,而是通过标准的栈操作—压栈和出栈—来访问的。比如,如果某个指令把一个值压入到操作数栈中,稍后另一个指令就可以弹出这个值来使用。 The virtual machine stores the same data types in the operand stack that it stores in the local variables: int,long, float, double, reference, and returnType. It converts values of type byte, short, and char to int before pushing them onto the operand stack. ...

2012-09-19 · 3 min · 428 words · -

int 和 Integer

int 和 Integer Java 提供两种不同的类型: 引用类型和原始类型 (或内置类型) 。Int是java的原始数据类型,Integer是java为int提供的封装类。Java为每个原始类型提供了封装类(Wrapper)。 原始类型 封装类 boolean Boolean char Character byte Byte short Short int Integer long Long float Float double Double 引用类型和原始类型的行为完全不同,并且它们具有不同的语义。引用类型和原始类型具有不同的特征和用法,它们包括: 大小和速度问题,这种类型以哪种类型的数据结构存储,当引用类型和原始类型用作某个类的实例数据时所指定的缺省值。对象引用实例变量的缺省值为 null,而原始类型实例变量的缺省值与它们的类型有关。 http://www.ibm.com/developerworks/cn/java/praxis/pr8.html

2012-09-19 · 1 min · 30 words · -

java 基本数据类型, primitive type

java 基本数据类型, primitive type Java语言提供了八种基本类型: 六种数字类型 (四个整数型,两个浮点型) ,一种字符类型,一种布尔型。 整数: 包括 int, short, byte, long 浮点型: float, double 字符: char 布尔: boolean java.lang.String 类是final类型的,因此不可以继承这个类、不能修改这个类。为了提高效率节省空间,应该用StringBuffer类 (1个字节是8个bit) 整数型: byte (1字节) 、short (2字节) 、int (4字节) 、long (8字节) 浮点型: float (4字节) 、double (8字节) 布尔型: boolean (1字节) 字符型: char (2字节) boolean: boolean数据类型表示一位的信息; 只有两个取值: true和false; 这种类型只作为一种标志来记录true/false情况; 默认值是false; 例子: boolean one = true。 byte 8位有符号整数 byte是一个字节保存的,有8个位. byte取值的范围: -128—127 8位的第一个位是符号位, 0000 0001代表的是数字1 1000 0000代表的就是-1 正数最大为0111 1111,是数字127 负数最大为1111 1111,是数字-128 在java中采用的是补码的形式. ...

2012-09-19 · 2 min · 267 words · -

Java 动态方法调用

Java 动态方法调用 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://wujuxiang.blog.51cto.com/2250829/406802 在Java中,如果方法重写只是一种名字空间的编写,那么它最多是让人感到有趣,但没有实际价值,但情况并非如此。方法重写构造成了Java最大的一个概念基础: 动态方法调度 (dynamic method dispatch) 。动态方法调度是一种机制,借助于这种机制,对一个已经重写的方法的调用将在运行时,而不是在编译时解析。动态方法调度非常重要,因为这关系到Java如何实现运行多态性的问题。我们知道,超类引用变量可以引用子类对象,Java使用这个事实来解决在运行时对重写方法的调用。下面是运行原理: 当一个超类引用调用一个重写方法时,Java根据在调用时被引用对象的类型执行哪个版本的方法。换句话说,是被引用对象的类型 (不是引用变量的类型) 决定将执行哪个版本的重写方法。因此,如果说超类包含一个被子类重写的方法,那么当通过超类引用变量来引用不同类型的对象时,就会执行那个方法的不同版本。演示如下: public class ClassA { void callme(){ System.out.println(“Inside A’s callme method”); } } public class ClassB extends ClassA{ void callme(){ System.out.println(“Inside B’s callme method”); } } public class ClassC extends ClassA{ void callme(){ System.out.println(“Inside C’s callme method”); } } public class Dispatch { public static void main(String[] args) { ClassA classA = new ClassA(); ClassB classB = new ClassB(); ClassC classC = new ClassC(); ...

2012-09-19 · 1 min · 113 words · -

多态性 polymorphism

多态性, polymorphism, /pɑlɪˈmɔrfɪzm/ 一个接口(方法或函数)表现出不同的行为。 多态的实现方式 继承与重写(Override):子类继承父类并重写父类的方法,通过父类引用或指针调用时,会执行子类重写后的方法。 接口(Interface):实现同一个接口的不同类,可以以统一的方式调用接口方法,实际执行的是各个类自己的实现。 什么是多态 多态的概念: 多态(Polymorphism)这个概念最早来自于生物学,表示的是同一物种在同一种群中存在两种或多种明显不同的表型。比如:在南美种群中存在两种颜色的美洲虎:浅黄色的和黑色的。 而在面向对象编程思想中,这个概念表达的是具有共性的类型,在执行相同的行为时,会体现出不同的实现方式。我们可以简称为:相同的行为,不同的实现。 比如:同样看到对面过来一个美女,男人和女人的想法是不一样的。 https://hyktech.gitee.io/javatech/2017/09/01/%E5%A4%9A%E6%80%81/ 多态性是指允许不同类的对象对同一消息作出响应。多态性包括参数化多态性和包含多态性。多态性语言具有灵活、抽象、行为共享、代码共享的优势,很好的解决了应用程序函数同名问题。 从广义上说,多态性是指一段程序能够处理多种类型对象的能力。在 c++ 语言中,这种多态性可以通过强制多态、重载多态、类型参数化多态、包含多态4种形式来实现。 类型参数化多态和包含多态统称为一般多态性,用来系统地刻画语义上相关的一组类型。重载多态和强制多态统称为特殊多态性,用来刻画语义上无关联的类型间的关系。 包含多态是指通过子类型化,1个程序段既能处理类型t的对象,也能够处理类型t的子类型s的对象,该程序段称为多态程序段。公有继承能够实现子类型。在包含多态中,1个对象可以被看作属于不同的类,其间包含关系的存在意味着公共结构的存在。包含多态在不少语言中存在,如整数类型中的子集构成1个子类型。每一个子类型中的对象可以被用在高一级的类型中,高一级类型中的所有操作可用于下一级的对象。在c++中公有继承关系是一种包含多态,每一个类可以直接公有继承父类或多个父类, 类型参数化多态是指当1个函数(类)统一地对若干类型参数操作时,这些类型表现出某些公共的语义特性,而该函数(类)就是用来描述该特性的。在类型参数化多态中,1个多态函数(类)必须至少带有1个类型参数,该类型参数确定函数(类)在每次执行时操作数的类型。这种函数(类)也称类属函数(类)。类型参数化多态的应用较广泛,被称为最纯的多态。 重载是指用同一个名字命名不同的函数或操作符。函数重载是c++对一般程序设计语言中操作符重载机制的扩充,它可使具有相同或相近含义的函数 用相同的名字,只要其参数的个数、次序或类型不一样即可 java 多态: class A { public String show(D obj) { return "A and D"; } public String show(A obj) { return "A and A"; } } class B extends A { public String show(B obj) { return "B and B"; } public String show(A obj) { return "B and A"; } } class C extends B { } class D extends B { } public class Test { public static void main(String[] args) { A a1 = new A(); A a2 = new B(); B b = new B(); C c = new C(); D d = new D(); System.out.println(a1.show(b)); System.out.println(a1.show(c)); System.out.println(a1.show(d)); System.out.println(a2.show(b)); // 4. output: B and A System.out.println(a2.show(c)); // 5. output: B and A System.out.println(a2.show(d)); // 6. output: A and D System.out.println(b.show(b)); System.out.println(b.show(c)); System.out.println(b.show(d)); } } 输出 ...

2012-09-19 · 3 min · 491 words · -

封装

封装 封装是把过程和数据包围起来,对数据的访问只能通过已定义的界面。面向对象计算始于这个基本概念,即现实世界可以被描绘成一系列完全自治、封装的对象,这些对象通过一个受保护的接口访问其他对象。

2012-09-19 · 1 min · 2 words · -

内存分页

内存分页 内存分页, paging 为什么要分页 分段的内存碎片太大,是计算中发展过程中尝试过的方案,现在的方案是内存分页,通过某种方式,将虚拟地址映射到物理地址,映射的关系是通过一张表实现的,也就是页表。 分页机制 分页机制的思想是:通过映射,可以使连续的线性地址与物理地址相关联,逻辑上连续的线性地址对应的物理地址可以不连续。 分页的作用 - 将线性地址转换为物理地址 - 用大小相同的页替换大小不同的段 一级页表 我们把一页的大小定义为4K,那么4G就有1M个页,在32位的保护模式下,地址都是32位二进制表示的,用20位二进制定位页表,剩余的12位表示4K里面的偏移。 分页机制打开前要将页表地址加载到控制寄存器CR3中,这个过程是打开页表之前,所以存储的是物理实际地址,每个页表项对应一个物理页,通过页表项就可以访问到实际的物理地址。由于这个过程是固定的,CPU中集成了这个硬件模块,即MMU中的页部件。 二级页表 为什么要二级页表 每个进程1M个页表,每个4字节,进程多了占用的内存还是很多的。 一般进程使用的内存是远低于全部虚拟内存的。二级模式只为进程实际使用的那些虚拟内存区分配页表,既提升了效率,也减少了内存的使用量。 作者:长安 链接:https://www.zhihu.com/question/50796850/answer/654281605 来源:知乎 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 作者:Ideal 链接:https://www.zhihu.com/question/50796850/answer/1449056116 来源:知乎 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 我觉得这个问题下目前的回答并没有讲清楚分段和分页的区别,有的答案甚至有错误,我尝试给一个我认为正确的理解。要回答为什么计算机中的内存访问会有分段机制,最好的方式是回到当时首次出现分段机制的历史背景下去考虑这个问题。事实上,对于计算机领域的诸多问题,很多时候工程上的选择都是完全跟当时的历史背景联系紧密的。并且因为硬件软件两个方面在过去几十年中都经历了极速的甚至是面目全非的发展,所以如果你不回溯背景,可能永远没有办法真正理解这些选择,分段最开始是从Intel的8086CPU,受限于价格和技术水平,当时的CPU和寄存器的宽度仍然为16位。那个时候还没有演化成像现在这样如此复杂的内存管理模式,程序在访问内存的时候还是直接给出相应单元的实际物理地址。为了便利地实现多道程序并发运行,也就需要支持对各个程序进行重定位,因为如果不支持重定位,凡是涉及到内存访问的地方都需要将地址硬编码,进而必须把某个程序加载到内存的固定区间。有了分段机制,程序中只需要使用基于段的相对地址,然后更改段基址,就可以方便地对程序进行重定位。当然,在8086CPU中,分段除了服务于重定位的目的,还有其他的作用。具体地说,8086CPU的地址线宽度是20位,可寻址的最大内存空间是1MB,但寄存器这些都是16位, 它是通过段加偏移的方式生成20位的地址,从而实现对1MB内存空间的寻址的。我们经常谈的程序可执行文件的分段,例如代码段数据段这些,在最开始其实就是为了跟上面描述的硬件上的内存分段机制对应,并且逻辑上能够更清晰有序地构造程序的组织结构。所以,总结来说,分段其实是80*86系列CPU的legacy。对于现代操作系统来说,由于已经引入了分页,分段更多的是一种历史包袱,而不是能够提供多大实际作用的内存管理机制。比如,The Linux Programming Interface那本书里就谈到:Linux uses segmentation in a very limited way. In fact, segmentation and paging are somewhat redundant, because both can be used to separate the physical address spaces of processes: segmentation can assign a different linear address space to each process, while paging can map the same linear address space into different physical address spaces. 事实上,通过将 cs (代码段) 和 ds (数据段) 寄存器的值设为0,Linux实际没有使用分段而只使用了分页。因为这样内存管理会更加简单,并且由于像RISC架构的处理器只对分段提供了非常有限的支持,不使用分段会提高Linux操作系统在不同CPU架构上的可移植性。 ...

2012-09-19 · 1 min · 123 words · -

过程抽象 数据抽象

过程抽象 数据抽象 抽象就是忽略一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方面。抽象并不打算了解全部问题,而只是选择其中的一部分,暂时不用部分细节。抽象包括两个方面,一是过程抽象,二是数据抽象。 数据抽象就是针对对象的属性,比如建立一个鸟这样的类,鸟会有以下特征,两个翅膀,两支脚,有羽毛等等特性,写成类都是鸟的属性 过程抽象就是针对对象的行为特征,比如鸟会飞,会跳等等,这些方面的就会抽象为方法,即过程,写成类都是鸟的方法 抽 象——就是把现实世界中的某一类东西,提取出来,用程序代码表示,抽象出来一般叫做类或者接口。 数据抽象——就是用代码的形式,表示现实世界中一类事物的特性,比如人的姓名,年龄等,抽象出来一般叫做属性或者成员变量等。 抽象过程——就是用代码的形式,表示现实世界中事物的一系列行为,比如人可以吃饭等,抽象出来一般叫做方法。

2012-09-19 · 1 min · 9 words · -

Python Hello World

Python Hello World install python3 pip3 sudo dnf install python3 http://blog.csdn.net/pjeby/article/details/1212592 简介 我们将看一下如何用Python编写运行一个传统的"Hello World"程序。通过它,你将学会如何编写、保存和运行Python程序。 有两种使用Python运行你的程序的方式——使用交互式的带提示符的解释器或使用源文件。我们将学习这两种方法。 使用带提示符的解释器 在命令行的shell提示符下键入python,启动解释器。现在输入print 'Hello World',然后按Enter键。你应该可以看到输出的单词Hello World。 对于Windows用户,只要你正确的设置了PATH变量,你应该可以从命令行启动解释器。或者你可以选择使用IDLE程序。IDLE是集成开发环境的缩写。点击开始->程序->Python 2.3->IDLE(Python GUI)。Linux用户也可以使用IDLE。 注意,>>>是你键入Python语句的提示符。 例1 使用带提示符的Python解释器 $ python Python 2.4.3 (#1, Jul 26 2006, 16:42:40) [GCC 3.4.2 20050110 (Red Hat 3.4.2-6.fc3)] on linux2 Type “help”, “copyright”, “credits” or “license” for more information. print ‘hello world’ hello world 注意,Python会在下一行立即给出你输出!你刚才键入的是一句Python 语句 。我们使用print (不要惊讶) 来打印你提供给它的值。这里,我们提供的是文本Hello World,它被迅速地打印在屏幕上。 如何退出Python提示符: 如果你使用的是Linux/BSD shell,那么按Ctrl-d退出提示符。如果是在Windows命令行中,则按Ctrl-z再按Enter。 挑选一个编辑器 在我们开始讲述以源文件方式编写Python程序之前,我们需要一个编辑器来写源文件。挑选一个编辑器确实是极其重要的。你挑选一个编辑器就如同你挑选一辆你将购买的轿车一样。一个好的编辑器会帮助你方便地编写Python程序,使你地编程旅程更加舒适,帮助你更加快捷安全地到达目的地 (实现目标) 。 ...

2012-09-19 · 1 min · 200 words · -

Markdown 语法

Markdown 语法 JetBrain Writerside implements the CommonMark Spec: https://spec.commonmark.org/0.30/ 转义 比如在 Markdown 中显示反引号, 可以用反斜杠转义 ` 字体 加粗 要加粗的文字左右分别用两个*号包起来 斜体 要倾斜的文字左右分别用一个*号包起来 *foo* foobarfoo 斜体加粗 要倾斜和加粗的文字左右分别用三个*号包起来 删除线 要加删除线的文字左右分别用两个~~号包起来 示例 这是加粗的文字 这是倾斜的文字 这是斜体加粗的文字 这是加删除线的文字 标题 # 一级标题 ## 二级标题 ### 三级标题 #### 四级标题 ##### 五级标题 ###### 六级标题 图片 ![Alt text](图片链接 "optional title") # 本地图片 ![avatar](/user/desktop/doge.png) # 网络图片 ![avatar](https://dubbo.apache.org/imgs/v3/concepts/threecenters.png) ![](https://dubbo.apache.org/imgs/v3/concepts/threecenters.png) 表格 | t0 | t1 | | - | - | | c0r0 | c1r0| | c1r1 | c1r1 | 引用 >foo Markdown 是一种轻量级的标记语言,由John Gruber和Aaron Swartz创建,使其成为可读性最大并可再发行的可输入输出的格式。这种语言创建灵感来自于已经存在的带标记的电子邮件文本。Markdown 允许 HTML 语法,所以使用者如果需要可以直接用 HTML来表示是可以的。Markdown最初由Gruber应用在Perl语言中,但现在已经有多种编程语言应用了。它是开源项目,并以BSD-style许可证的许可方式以插件形式或内容管理系统形式发布。 ...

2012-09-17 · 1 min · 174 words · -

excel round、rounddown、roundup

excel round、rounddown、roundup round、rounddown、roundup三个函数应用的区别。 round函数: 按指定位数对数字进行四舍五入。如输入=round(3.158,2) 则会出现数字3.16,即按两位小数进行四舍五入。rounddown: 按指定位数舍去数字指定位数后面的小数。如输入=rounddown(3.158,2) 则会出现数字3.15,将两位小数后的数字全部舍掉了。 roundup: 按指定位数向上舍入指定位数后面的小数。如输入=roundup(3.158,2) 则会出现数字3.16,将两位小数后的数字舍上去,除非其后为零。 注: 其中的3.158可更改为单元格如A1,小数位数也可自行更改。其他的可以照搬。

2012-09-17 · 1 min · 13 words · -

excel 函数

’excel 函数' 判断相等 sum 函数是求和函数。它是excel函数中最为常用的函数之一,sum函数分别出现在数学函数、全部函数两个类别中,默认的"常用函数"中也有。 sum函数的语法形式为: sum(number1,number2, …) sum函数的注意事项: 函数的语法中number1,number2等参数,最多有30个; 函数的语法中number1,number2等参数,既可以是数字 (例1) ,也可以是逻辑值 (例3) ,也可以是表达式 (例3) ,也可以是单元格名称,也可以是连续单元格的集合 (例2) ,也可以是单元格区域名称,并且以上所列类别将会被计算; 如果number1等参数为单元格名称、连续单元格集合、单元格区域名称则只计算其中的数值和函数公式数值结果部分,不计算逻辑值、表格中的文字表达式 (例4) ; sum函数示例: 样表 A 1 3 2 1 3 1+2 4 (1+2=3) 5 3d 上表中A为列号,左侧1-5为行号。 若在A6单元格输入以下公式的结果: 例1、=sum(1,2,3) 结果为6,计算1、2、3三个数字的和; 例2、=sum(a1:a2) 结果为4,计算a1到a2单元格之和; 例3、=sum((1+2=3),(1+2),(a1:a2) 结果为8,因为(1+2=3)表达式的结果为真,在电脑中的结果为1,1+2表达式的结果3会被计算,a1到a2单元格之和4会被计算,所以最后的结果为8; 例4、=sum(a1:a5) 结果为4,不计算引用单元格中的文字表达式 (1+2) 、逻辑表达式 ((1+2=3)) 、不计算字符; 本文是 有图博客 原创,原地址 http://www.utosee.com/excel/sum.html 转载请保留。

2012-09-17 · 1 min · 54 words · -

jodatime date

jodatime date function currentTime(){ var d = new Date(),str = “; str += d.getFullYear()+‘年’; str += d.getMonth() + 1+‘月’; str += d.getDate()+‘日’; str += d.getHours()+‘时’; str += d.getMinutes()+‘分’; str+= d.getSeconds()+‘秒’; return str; }

2012-09-16 · 1 min · 33 words · -

java List 排序 Collections.sort() 对 List 排序

java List 排序 Collections.sort() 对 List 排序 java.util.Comparator 接口。要实现里面的函数 int compare(Object o1, Object o2) 返回一个基本类型的整型,返回负数表示o1 小于o2,返回0 表示o1和o2相等,返回正数表示o1大于o2。 class User { String name; String age; public User(String name,String age){ this.name=name; this.age=age; } public String getAge() { return age; } public void setAge(String age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } } //具体的比较类,实现Comparator接口 import java.util.Comparator; import java.util.List; import java.util.ArrayList; import java.util.Collections; public class ComparatorUser implements Comparator{ public int compare(Object arg0, Object arg1) { User user0=(User)arg0; User user1=(User)arg1; //首先比较年龄,如果年龄相同,则比较名字 int flag=user0.getAge().compareTo(user1.getAge()); if(flag==0){ return user0.getName().compareTo(user1.getName()); }else{ return flag; } } } //测试类 public class SortTest { public static void main(String[] args){ List userlist=new ArrayList(); userlist.add(new User("dd","4″)); userlist.add(new User("aa","1″)); userlist.add(new User("ee","5″)); userlist.add(new User("bb","2″)); userlist.add(new User("ff","5″)); userlist.add(new User("cc","3″)); userlist.add(new User("gg","6″)); ComparatorUser comparator=new ComparatorUser(); Collections.sort(userlist, comparator); for (int i=0;i<userlist.size();i++){ User user_temp=(User)userlist.get(i); System.out.println(user_temp.getAge()+","+user_temp.getName()); } } } //首先年龄排序,如果年龄相同,则按名字排序 "\`java 结果: 1, aa 2, bb 3, cc 4, dd 5, ee //注意:同样是5岁的人,则比较名字(ee,ff),然后排序 5, ff 6, gg http://www.blogjava.net/zygcs/archive/2008/01/17/176032.html http://muscle-liu.iteye.com/blog/157261

2012-09-16 · 1 min · 162 words · -

公有云安装 archlinux, Aliyun/阿里云 ecs, bwg KVM

aliyun ecs, 阿里云安装 archlinux aliyun vm 安装 非 EFI 的镜像 cd /tmp curl -O http://mirrors.163.com/archlinux/iso/2024.04.01/archlinux-bootstrap-2024.04.01-x86_64.tar.gz tar zxvf archlinux-bootstrap-xxx.tar.gz # 要用 mount --bind 把 RootFS 解包的目录自己与自己链接起来,不然 pacman 会装不了软件 sudo mount --bind /tmp/root.x86_64 /tmp/root.x86_64 # edit mirror list vim /tmp/root.x86_64/etc/pacman.d/mirrorlist # chroot /tmp/root.x86_64/bin/arch-chroot /tmp/root.x86_64/ # 初始化 pacman 的密钥 pacman-key --init pacman-key --populate archlinux # 把 原系统的 根目录 / 挂载到 /mnt # 先 df -h 看一下 根目录在哪个分区 mount /dev/vdaX /mnt # 保留的目录 /dev /proc /run /sys /tmp , 这些目录都是存储到硬件的映射的,所以不能删 # boot 目录有可能会删除失败 rm -rf /mnt/boot rm -rf /mnt/bin rm -rf /mnt/data rm -rf /mnt/etc rm -rf /mnt/home rm -rf /mnt/lib rm -rf /mnt/lib32 rm -rf /mnt/lib64 rm -rf /mnt/libx32 rm -rf /mnt/media rm -rf /mnt/mnt rm -rf /mnt/opt rm -rf /mnt/root rm -rf /mnt/sbin rm -rf /mnt/srv rm -rf /mnt/usr rm -rf /mnt/var pacstrap /mnt base linux linux-firmware genfstab -U /mnt >> /mnt/etc/fstab arch-chroot /mnt ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime echo 'nameserver 114.114.114.114' >> resolv.conf pacman -S gvim openssh grub sudo neofetch python echo 'aliyun0' > /etc/hostname echo '127.0.0.1 localhost' >> /etc/hosts echo '127.0.0.1 aliyun0' >> /etc/hosts systemctl enable systemd-networkd systemctl enable systemd-resolved systemctl enable sshd vim /etc/systemd/network/eth.network [Match] Name=en* [Network] DHCP=ipv4 [DHCPv4] UseHostname=false useradd -m wiloon passwd wiloon passwd root echo 'wiloon ALL=(ALL) NOPASSWD: ALL' > /etc/sudoers.d/wiloon.conf grub-install --target=i386-pc /dev/vda grub-mkconfig -o /boot/grub/grub.cfg reboot timedatectl set-ntp true -` root@aliyun0 .o+` ------------ `ooo/ OS: Arch Linux x86_64 `+oooo: Host: Alibaba Cloud ECS pc-i440fx-2.1 `+oooooo: Kernel: 6.8.7-arch1-1 -+oooooo+: Uptime: 6 mins `/:-:++oooo+: Packages: 254 (pacman) `/++++/+++++++: Shell: bash 5.2.26 `/++++++++++++++: Resolution: 1024x768 `/+++ooooooooooooo/` Terminal: /dev/pts/0 ./ooosssso++osssssso+` CPU: Intel Xeon Platinum 8269CY (2) @ 2.500GHz .oossssso-````/ossssss+` GPU: 00:02.0 Cirrus Logic GD 5446 -osssssso. :ssssssso. Memory: 93MiB / 422MiB :osssssss/ osssso+++. /ossssssss/ +ssssooo/- `/ossssso+/:- -:/+osssso+- `+sso+:-` `.-/+oso: `++:. `-/+/ .` `/ https://limelight.moe/t/topic/6007 https://www.scarletdrop.cn/archives/14 ...

2012-09-16 · 2 min · 305 words · -

Spring中bean的作用域

Spring中bean的作用域 http://blog.csdn.net/ProvidenceZY/article/details/1878582 如何使用spring的作用域: <bean id="role" class="spring.chapter2.maryGame.Role" scope="singleton"/> 这里的scope就是用来配置spring bean的作用域,它标识bean的作用域。 在spring2.0之前bean只有2种作用域即: singleton(单例)、non-singleton (也称prototype) , Spring2.0以后,增加了session、request、global session三种专用于Web应用程序上下文的Bean。因此,默认情况下Spring2.0现在有五种类型的Bean。当然,Spring2.0对Bean的类型的设计进行了重构,并设计出灵活的Bean类型支持,理论上可以有无数多种类型的Bean,用户可以根据自己的需要,增加新的Bean类型,满足实际应用需求。 1、singleton作用域 当一个bean的作用域设置为singleton, 那么Spring IOC容器中只会存在一个共享的bean实例,并且所有对bean的请求,只要id与该bean定义相匹配,则只会返回bean的同一实例。换言之,当把一个bean定义设置为singleton作用域时,Spring IOC容器只会创建该bean定义的唯一实例。这个单一实例会被存储到单例缓存 (singleton cache) 中,并且所有针对该bean的后续请求和引用都将返回被缓存的对象实例,这里要注意的是singleton作用域和GOF设计模式中的单例是完全不同的,单例设计模式表示一个ClassLoader中只有一个class存在,而这里的singleton则表示一个容器对应一个bean,也就是说当一个bean被标识为singleton时候,spring的IOC容器中只会存在一个该bean。 配置实例: <bean id="role" class="spring.chapter2.maryGame.Role" scope="singleton"/> 或者 <bean id="role" class="spring.chapter2.maryGame.Role" singleton="true"/> 2、prototype prototype作用域部署的bean,每一次请求 (将其注入到另一个bean中,或者以程序的方式调用容器的getBean()方法) 都会产生一个新的bean实例,相当与一个new的操作,对于prototype作用域的bean,有一点非常重要,那就是Spring不能对一个prototype bean的整个生命周期负责,容器在初始化、配置、装饰或者是装配完一个prototype实例后,将它交给客户端,随后就对该prototype实例不闻不问了。不管何种作用域,容器都会调用所有对象的初始化生命周期回调方法,而对prototype而言,任何配置好的析构生命周期回调方法都将不会被调用。清除prototype作用域的对象并释放任何prototype bean所持有的昂贵资源,都是客户端代码的职责。 (让Spring容器释放被singleton作用域bean占用资源的一种可行方式是,通过使用bean的后置处理器,该处理器持有要被清除的bean的引用。) 配置实例: <bean id="role" class="spring.chapter2.maryGame.Role" scope="prototype"/> 或者 <beanid="role" class="spring.chapter2.maryGame.Role" singleton="false"/> 3、request request表示该针对每一次HTTP请求都会产生一个新的bean,同时该bean仅在当前HTTP request内有效,配置实例: request、session、global session使用的时候首先要在初始化web的web.xml中做如下配置: 如果你使用的是Servlet 2.4及以上的web容器,那么你仅需要在web应用的XML声明文件web.xml中增加下述ContextListener即可: <web-app> … org.springframework.web.context.request.RequestContextListener … ...

2012-09-16 · 1 min · 191 words · -