python:内存管理

变量无类型,对象有类型 —《learning python》

语言的内handlerhandhandler存管理是语言设计的一个重要方面。它是决定语言性能的重要因素。无论是C语言的手工管理,还是Java的垃圾回收,都成为语言最重要的特征。这里以Python语言为例子,说明一门动态类型的、面向对象的语言的内存管理方式。

对象内存的使用

Python是动态类型的语言 ,对象与引用分离。Python像使用“筷子”那样,通过引用来接触和翻动真正的食物——对象。

几 个有用的函数:

  1. 为了探索对象在内存的存储,我们可以求助于Python的内置函数id()。它用于返回对象的身份(identity)。其实,这里所谓的身份,就是该对象的内存地址
  2. 在Python中,每个对象都有存有指向该对象的引用总数,即引用计数(reference count)。我们可以使用sys包中的getrefcount()来查看某个对象的引用计数。
  3. 对象引用对象,是Python最基本的构成方式。即使是a = 1这一赋值方式,实际上是让词典的一个键值”a”的元素引用整数对象1。该词典对象用于记录所有的全局引用。该词典引用了整数对象1。我们可以通过内置函数globals()来查看该词典。
  4. 为了检验两个引用指向同一个对象,我们可以用is关键字。is用于判断两个引用所指的对象是否相同。其实等价于id(a)==id(b)

JAVA:类型

Java的数据类型有两种:

  • 基本数据类型
  • 普通数据类型(引用数据类型)

基本数据类型

8种基本类型

4种整型

  • byte 1字节 -128——127
  • short 2 字节 -32,768 —— 32,767
  • int 4 字节 -2,147,483,648 ——2,147,483,647(超过20亿)
  • long 8 字节 -9,223,372,036,854,775,808——9,223,372,036854,775,807

Linux IP 命令使用详解

Linux IP命令使用详解

简介

作用

ip是iproute2软件包里面的一个强大的网络配置工具,它能够替代一些传统的网络管理工具,例如ifconfigroute等,使用权限为超级用户。几乎所有的Linux发行版本都支持该命令。

格式

ip [OPTIONS] OBJECT [COMMAND [ARGUMENTS]]

SSD装ubuntu及优化

憋了好久终于趁着双十一去京东买了块东芝的固态硬盘(240G), 然后把旧的那块硬盘给丢到一边,尽情享受SSD带来的极速体验

装系统

我的计划是单系统, 放弃一直以来的双系统。
SSD一个很重要的概念就是4K对齐, 这个对linux来说根本不是问题, 在用U盘装系统时,选择自己分区, 自动会4K对齐。 至于ahck这个一般也是默认开启的, 自己开机的时候去bios看一下。
这里要注意, 装系统时要选择自己分区, 不然ubuntu会自动的只给你分了一个swap的交换空间, 然后全部的空间都分配给/, 这样使用linux很不应该, 因为这样重装系统是很麻烦

JAVA:IO详解

知识基础

学习Java IO,不得不提到的就是JavaIO流。

流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象。即数据在两设备间的传输称为流,流的本质是数据传输,根据数据传输特性将流抽象为各种类,方便更直观的进行数据操作。
根据处理数据类型的不同分为:字符流和字节流
根据数据流向不同分为:输入流和输出流

字符流和字节流

字符流的由来: 因为数据编码的不同,而有了对字符进行高效操作的流对象。本质其实就是基于字节流读取时,去查了指定的码表。字节流和字符流的区别:

(1)读写单位不同:字节流以字节(8bit)为单位,字符流以字符为单位,根据码表映射字符,一次可能读多个字节。
(2)处理对象不同:字节流能处理所有类型的数据(如图片、avi等),而字符流只能处理字符类型的数据
(3)字节流在操作的时候本身是不会用到缓冲区的,是文件本身的直接操作的;而字符流在操作的时候下后是会用到缓冲区的,是通过缓冲区来操作文件,我们将在下面验证这一点。

结论:优先选用字节流。首先因为硬盘上的所有文件都是以字节的形式进行传输或者保存的,包括图片等内容。但是字符只是在内存中才会形成的,所以在开发中,字节流使用广泛。

JAVA:容器

Java中有一些对象被称为容器(container)容器中可以包含多个对象,每个对象称为容器中的一个元素。容器是用对象封装的数据结构(data structure)。
java容器

1
2
3
4
5
6
7
8
9
10
11
12
Array
Collection
├-List
│ ├-LinkedList
│ ├-ArrayList
│ └-Vector
│  └Stack
└-Set
Map
├-Hashtable
├-HashMap
└-WeakHashMap

JAVA:内存管理

Java是在JVM所虚拟出的内存环境中运行的。内存分为栈(stack)和堆(heap)两部分。我们将分别考察这两个区域。

许多语言利用栈数据结构来记录函数调用的次序和相关变量

在Java中,JVM中的栈记录了线程的方法调用。每个线程拥有一个栈。在某个线程的运行过程中,如果有新的方法调用,那么该线程对应的栈就会增加一个存储单元,即帧(frame)。在frame中,保存有该方法调用的参数、局部变量和返回地址。
enter image description here

Java的参数和局部变量只能是基本类型的变量(比如int),或者对象的引用(reference)。因此,在栈中,只保存有基本类型的变量和对象引用。

引用所指向的对象保存在堆中。(引用可能为Null值,即不指向任何对象)当被调用方法运行结束时,该方法对应的帧将被删除,参数和局部变量所占据的空间也随之释放。线程回到原方法,继续执行。当所有的栈都清空时,程序也随之运行结束。

如上所述,栈(stack)可以自己照顾自己。但堆必须要小心对待。堆是JVM中一块可自由分配给对象的区域。当我们谈论垃圾回收(garbage collection)时,我们主要回收堆(heap)的空间。

Java的普通对象存活在堆中。与栈不同,堆的空间不会随着方法调用结束而清空。因此,在某个方法中创建的对象,可以在方法调用结束之后,继续存在于堆中。这带来的一个问题是,如果我们不断的创建新的对象,内存空间将最终消耗殆尽。

垃圾回收

垃圾回收(garbage collection,简称GC)可以自动清空堆中不再使用的对象。 垃圾回收是Java的一大特征。并不是所有的语言都有垃圾回收功能。比如在C/C++中,并没有垃圾回收的机制。程序员需要手动释放堆中的内存。

如果不再有引用指向对象,那么我们就再也无从调用或者处理该对象。这样的对象将不可到达(unreachable)。垃圾回收用于释放不可到达对象所占据的内存。这是垃圾回收的基本原则。

早期的垃圾回收采用引用计数(reference counting)的机制。每个对象包含一个计数器。当有新的指向该对象的引用时,计数器加1。当引用移除时,计数器减1。当计数器为0时,认为该对象可以进行垃圾回收。

然而,一个可能的问题是,如果有两个对象循环引用(cyclic reference),比如两个对象互相引用,而且此时没有其它(指向A或者指向B)的引用,我们实际上根本无法通过引用到达这两个对象。

因此,我们以栈和static数据为根(root),从根出发,跟随所有的引用,就可以找到所有的可到达对象。也就是说,一个可到达对象,一定被根引用,或者被其他可到达对象引用。

JVM的垃圾回收是多种机制的混合。JVM会根据程序运行状况,自行决定采用哪种垃圾回收。

  • 我们先来了解mark and sweep。这种机制下,每个对象将有标记信息,用于表示该对象是否可到达。当垃圾回收启动时,Java程序暂停运行。JVM从根出发,找到所有的可到达对象,并标记(mark)。随后,JVM需要扫描整个堆,找到剩余的对象,并清空这些对象所占据的内存。

  • 另一种是copy and sweep。这种机制下,堆被分为两个区域。对象总存活于两个区域中的一个。当垃圾回收启动时,Java程序暂停运行。JVM从根出发,找到可到达对象,将可到达对象复制到空白区域中并紧密排列,修改由于对象移动所造成的引用地址的变化。最后,直接清空对象原先存活的整个区域,使其成为新的空白区域。

可以看到,”copy and sweep”需要更加复杂的操作,但也让对象可以紧密排列,避免”mark and sweep”中可能出现的空隙。在新建对象时,”copy and sweep”可以提供大块的连续空间。因此,如果对象都比较”长寿“,那么适用于”mark and sweep”。如果对象的“新陈代谢“比较活跃,那么适用于”copy and sweep”。

上面两种机制是通过分代回收(generational collection)混合在一起的。每个对象记录有它的世代(generation)信息。所谓的世代,是指该对象所经历的垃圾回收的次数。世代越久远的对象,在内存中存活的时间越久。

根据对Java程序的统计观察,世代越久的对象,越不可能被垃圾回收(富人越富,穷人越穷)。因此,当我们在垃圾回收时,要更多关注那些年轻的对象。

enter image description here
当新建对象无法放入eden区时,将出发minor collection。JVM采用copy and sweep的策略,将eden区与from区的可到达对象复制到to区。经过一次垃圾回收,eden区和from区清空,to区中则紧密的存放着存活对象。随后,from区成为新的to区, to区成为新的from区。

如果进行minor collection的时候,发现to区放不下,则将部分对象放入成熟世代。另一方面,即使to区没有满,JVM依然会移动世代足够久远的对象到成熟世代。
如果成熟世代放满对象,无法移入新的对象,那么将触发major collection。JVM采用mark and sweep的策略,对成熟世代进行垃圾回收。

@refer Vamei

JAVA:RTTI

运行时类型识别(RTTI, Run-Time Type Identification)是Java中非常有用的机制,在Java运行时,RTTI维护类的相关信息。

多态(polymorphism)是基于RTTI实现的。RTTI的功能主要是由Class类实现的。

Class类

Class类是"类的类"(class of classes)。如果说类是对象的抽象和集合的话,那么Class类就是对类的抽象和集合

每一个Class类的对象代表一个其他的类。
当我们调用对象的getClass()方法时,就得到对应Class对象的引用。
String s="test "; Class c=s.getClass();

Java中每个对象都有相应的Class类对象,因此,我们随时能通过Class对象知道某个对象“真正”所属的类。无论我们对引用进行怎样的类型转换,对象本身所对应的Class对象都是同一个。当我们通过某个引用调用方法时,Java总能找到正确的Class类中所定义的方法,并执行该Class类中的代码。由于Class对象的存在,Java不会因为类型的向上转换而迷失。这就是多态的原理。

除了getClass()外还有其他返回Class对象的方法:

1
2
3
Class c1 = Class.forName("String");
Class c2 = String.class;
Class c3 =Class.forName(String.class.toString().replaceAll("class ",""));

linux感悟二三事

@author chenyun

  • Linux是用户易用型系统,但要成为他的用户很难.

    Linux is user-friendly. It’s just very selective about who its friends are

  • Linux和Windows二者最重要的区别乃是它们对自己的用户所做的假设。对于 Linux,这个假设是:用户知道自己想要什么,也明白自己在做什么,并且会为自己的行为负责。而 Windows 则恰好相反:用户不知道自己想要什么,也不明白自己在做什么,更不打算为自己的行为负责。
    造成的结果就是皮格马利翁效应

  • 用户是机器的主人,操作系统只是用户请来的助手;用户知道自己想要什么,明白自己在做什么,也会为自己的行为负责;操作系统尽量少说话,更不要下命令

  • Linux怎么读?看这里
    还有Linus Torvalds本人的一段录音:
    “hello,this is linus torvalds and i pronounce linux as linux[‘li:nэks]”
    但是

    Linux is free include its pronunciation

  • 命令行是最高效的方式

  • 条条大路通罗马, 但是不走Linux这条路, 大多数人甚至都不知道有罗马

  • 结束语: Linux真心让人爽

    Liberty means responsibility. That is why most men dread it. —  George Bernard Shaw
     Unless a man has talents to make something of himself, freedom is an irksome burden.  —  Eric Hoffer