Java 8 函数式接口 functional interface

Java 8 函数式接口 functional interface http://colobu.com/2014/10/28/secrets-of-java-8-functional-interface/ @FunctionalInterface 函数式接口(Functional Interface)是Java 8对一类特殊类型的接口的称呼。 这类接口只定义了唯一的抽象方法的接口 (除了隐含的Object对象的公共方法) , 因此最开始也就做SAM类型的接口 (Single Abstract Method) 。 为什么会单单从接口中定义出此类接口呢? 原因是在Java Lambda的实现中, 开发组不想再为Lambda表达式单独定义一种特殊的Structural函数类型,称之为箭头类型 (arrow type) , 依然想采用Java既有的类型系统(class, interface, method等), 原因是增加一个结构化的函数类型会增加函数类型的复杂性,破坏既有的Java类型,并对成千上万的Java类库造成严重的影响。 权衡利弊, 因此最终还是利用SAM 接口作为 Lambda表达式的目标类型。 JDK中已有的一些接口本身就是函数式接口,如Runnable。 JDK 8中又增加了java.util.function包, 提供了常用的函数式接口。 函数式接口代表的一种契约, 一种对某个特定函数类型的契约。 在它出现的地方,实际期望一个符合契约要求的函数。 Lambda表达式不能脱离上下文而存在,它必须要有一个明确的目标类型,而这个目标类型就是某个函数式接口。 当然, Java 8发布快一年了, 你对以上的概念也应该有所了解了,这篇文章也不会介绍这些基础的东西, 而是想深入的探讨函数式接口的定义和应用。 JDK 8之前已有的函数式接口 java.lang.Runnable java.util.concurrent.Callable java.security.PrivilegedAction java.util.Comparator java.io.FileFilter java.nio.file.PathMatcher java.lang.reflect.InvocationHandler java.beans.PropertyChangeListener java.awt.event.ActionListener javax.swing.event.ChangeListener 新定义的函数式接口 java.util.function中定义了几组类型的函数式接口以及针对基本数据类型的子接口。 Predicate - 传入一个参数,返回一个bool结果, 方法为boolean test(T t) Consumer - 传入一个参数,无返回值,纯消费。 方法为void accept(T t) ...

2014-12-24 · 4 min · 824 words · -

WinSCP 的四种协议:SFTP(SSH)、FTP、SCP、WebDAV

WinSCP的四种协议:SFTP(SSH)、FTP、SCP、WebDAV 1、FTP FTP(File Transfer Protocol,文件传输协议),通过端口进行文件传输: 端口21,控制链路,用于发送指令给服务器并等待服务器响应; 端口20,数据链路,用来建立数据传输通道。 使用FTP协议可能会存在一些安全隐患,例如FTP服务器软件的漏洞、明文口令、通过FTP服务器进行端口扫描、数据劫持等。 参考:https://baike.baidu.com/item/FTP协议/7651119?fr=aladdin 2.SFTP(SSH) SSH (SSH File Transfer Protocol) 又称 SFTP(Secret File Transfer Protocol),安全文件传送协议,为传输文件提供一种安全的加密方法。 SFTP是SSH内含的协议,只要SSHD服务器启动了就可用,不需要FTP服务器启动才能用。 对网络安全性要求高时,建议使用SFTP。由于SFTP采用加密传输认证信息和数据,所以SFTP十分安全,但是传输效率就比FTP要低的多。 参考:https://baike.baidu.com/item/SSH文件传输协议?fromtitle=sftp&fromid=1184182 3、SCP SCP(secure copy),用来进行远程文件拷贝,使用和SSH相同的认证方式,提供相同的安全保障。 参考:https://www.cnblogs.com/mxh1099/p/5554823.html 4、WebDAV WebDAV一种基于HTTP1.1的扩展协议, 在GET、POST、HEAD等几个HTTP标准方法以外添加了一些新的方法, 使应用程序对Web Server直接读写,并支持写文件锁定及解锁,还可以支持文件的版本控制。 参考:https://baike.baidu.com/item/WebDAV https://www.cnblogs.com/bors/p/WinSCP.html run winscp from cmd winscp.exe /ini="C:\Users\martin\Documents\myconfig.ini"

2014-12-23 · 1 min · 40 words · -

netdata

netdata pacman -S netdata systemctl start netdata systemctl enable netdata vim /etc/netdata/netdata.conf [web] bind to = 0.0.0.0 [::]

2014-12-23 · 1 min · 18 words · -

线程 工作内存

线程 工作内存 计算机的工作方式是基于冯诺依曼结构的,从磁盘读取数据到内存,再从内存读取数据到cpu内部的三级,二级,一级最后到达寄存器。java中的多线程的主内存就是内存上面的 jvm 堆,程序在运行时的线程所要的数据都是来自内存,读取并最终传入cpu内部寄存器,每个cpu内部都有各自的一套完整寄存器,cpu只能直接操作这些寄存器,比如cpu的加法指令吧两个寄存器里面的数据加起来放入其中一个或者地三个寄存器,计算的结果如需要保存,cpu需要另一个指令吧数据传输到数据总线并保存到内存,最终写回磁盘。在这个过程中,内存数据可能被多个线程同时读取,并在cpu内部形成私有的拷贝,就是本地内存 (内存的cpu内部本地副本) 在线程中体现在 线程栈 区,正是这种分步多指令实现一个操作,在多线程被调度置换过程中数据被多个线程操作,造成数据竞争,所以数据经常用到锁等手段实现同步。 上面从硬件的实现角度看,从软件的角度看,线程可访问的数据就分共享数据,和私有数据,这个在不同的计算机编程语言中体现都不一样,比如java中的类属性就可以是共享的也可以是私有的,当这个类的实例是在方法内部创建的,那属性就是线程私有的,因为整个对象都是线程私有的,如果该对象被传到线程中的方法,该对象就是共享的。这个界限就看数据是在哪里产生和多线程可访问性;线程防范内部产生并不被方法外部可访问的数据都是私有数据,多线程编程称为线程安全。相反线程不安全。 Java 虚拟机规范定义了 Java 内存模型来屏蔽掉各种硬件和操作系统的内存差异,达到跨平台的内存访问效果。 为了获得更好的执行性能,Java 内存模型没有限制执行引擎使用处理器的特定缓存器或缓存来和主内存(可以和 RAM类比,但是是虚拟机内存的一部分)交互,工作内存 (可类比高速缓存,也是虚拟机内存的一部分) 为线程私有。 工作内存和主内存的划分和 Java 堆,栈,方法区的划分不同,两者基本没有关系,如果勉强对应,则主内存可理 解为堆中实例数据部分,工作内存则对应栈中部分区域 –引用 «深入理解 JAVA 虚拟机» 线程栈 Execution stack 每个线程都有一个线程栈,线程的每个方法被执行的时候,都会同时创建一个帧 (Frame) 用于存储 本地变量表、操作栈、动态链接、方法出入口等信息。每一个方法的调用至完成,就意味着一个帧在VM栈中的入栈至出栈的过程。如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常;如果VM栈可以动态扩展 (VM Spec中允许固定长度的VM栈) ,当扩展时无法申请到足够内存则抛出 OutOfMemoryError异常。 一个栈帧又分为: 局部变量区、操作数栈和帧数据区。你可以理解 工作内存为局部变量区中的数据。 https://segmentfault.com/q/1010000004885908 https://www.oschina.net/question/1779843_2163094

2014-12-05 · 1 min · 43 words · -

Genymotion

Genymotion Genymotion是一套完整的工具集,旨在为Android提供虚拟环境。开发人员、测试人员、销售人员甚至是游戏玩家都能从中获得众多实用功 能。 它可用于大多数操作系统: Windows、Linux以及MacOS X。它既易于安装,又具备强大的功能: 遵循简单的安装流程指引、选择一款Android虚拟设备、启动工具,大功告成! http://mobile.51cto.com/android-405002.htm Genymotion Android 模拟器一直以速度奇慢无比著称,基本慢到不可用。本文介绍我一直在用的 Genymotion,速度不亚于真机。而且功能齐全,使用简单。 Genymotion 来自于 AndroVM 这个开源项目,基于 x86 和 VirtualBox,支持 OpenGL 加速,可以用于Mac/Win/Linux。最近发布了新版,支持了 Android2.3/4.3,新增了拖拽安装 apk,移除了 Google 市场 (后面提供解决方案) 。另外增加了功能更丰富的付费版,个人可以继续使用免费版。 https://www.imququ.com/post/genymotion.html http://mobile.51cto.com/android-405002.htm

2014-12-04 · 1 min · 29 words · -

Genymotion

Genymotion Genymotion是一套完整的工具集,旨在为Android提供虚拟环境。开发人员、测试人员、销售人员甚至是游戏玩家都能从中获得众多实用功 能。 它可用于大多数操作系统: Windows、Linux以及MacOS X。它既易于安装,又具备强大的功能: 遵循简单的安装流程指引、选择一款Android虚拟设备、启动工具,大功告成! http://mobile.51cto.com/android-405002.htm Genymotion Android 模拟器一直以速度奇慢无比著称,基本慢到不可用。本文介绍我一直在用的 Genymotion,速度不亚于真机。而且功能齐全,使用简单。 Genymotion 来自于 AndroVM 这个开源项目,基于 x86 和 VirtualBox,支持 OpenGL 加速,可以用于Mac/Win/Linux。最近发布了新版,支持了 Android2.3/4.3,新增了拖拽安装 apk,移除了 Google 市场 (后面提供解决方案) 。另外增加了功能更丰富的付费版,个人可以继续使用免费版。 https://www.imququ.com/post/genymotion.html

2014-12-04 · 1 min · 28 words · -

jvm Warmup

jvm Warmup Warmup Warmup 是指在实际进行 benchmark 前先进行预热的行为。为什么需要预热?因为 JVM 的 JIT 机制的存在,如果某个函数被调用多次之后,JVM 会尝试将其编译成为机器码从而提高执行速度。所以为了让 benchmark 的结果更加接近真实情况就需要进行预热。 http://blog.dyngr.com/blog/2016/10/29/introduction-of-jmh/

2014-12-03 · 1 min · 15 words · -

Create spring mvc project

Create spring mvc project gradle plugin: apply plugin: ‘idea’ apply plugin: ’eclipse' apply plugin: ‘war’ gradle dependencies: compile(“org.springframework:spring-core:$versionSpring”, “org.springframework:spring-context:$versionSpring”, “org.springframework:spring-web:$versionSpring”, “org.springframework:spring-webmvc:$versionSpring”, “org.springframework:spring-jdbc:$versionSpring”, “org.springframework:spring-orm:$versionSpring” ) web.xml create web.xml in …/webapp/WEB-INF/ http://www.wiloon.com/?p=3459 add context loader listener org.springframework.web.context.ContextLoaderListener spring schema index http://www.springframework.org/schema/beans/ Create controller /JavaEEX/src/main/java/com/wiloon/javaeex/controller/FooController.java create springMvc.xml for eclipse project convert project to web project

2014-12-03 · 1 min · 52 words · -

POSIX

POSIX Pronunciation: /ˈpɒz.ɪks/, pozz-icks POSIX代表 “可移植操作系统接口” Portable Operation System Interface。 在网上查到对于POSIX的介绍,来自《Linux内核设计与实现 (第2版) 》的第5章,就这部分来看,这本书估计不错。 一般情况下,应用程序通过应用编程接口(API)而不是直接通过 系统调用 来编程。这点很重要,因为应用程序使用的这种编程接口实际上并不需要和内核提供的系统调用对应。 一个API定义了一组应用程序使用的编程接口。它们可以实现成一个系统调用,也可以通过调用多个系统调用来实现, 而完全不使用任何系 统调用也不存在问题。 实际上,API可以在各种不同的操作系统上实现,给应用程序提供完全相同的接口,而它们本身在这些系统上的实现却可能迥异。 在Unix世界中,最流行的应用编程接口是基于POSIX标准的。从纯技术的角度看,POSIX是由IEEE的一组标准组成,其目标是提供一套大体上基于Unix的可移植操作系统标准。Linux是与POSIX兼容的。 POSIX是说明API和系统调用之间关系的一个极好例子。在大多数Unix系统上,根据POSIX而定义的API函数和系统调用之间有着直接关 系。实际上,POSIX标准就是仿照早期Unix系统的界面建立的。另一方面,许多操作系统,像Windows NT,尽管和Unix没有什么关系,也提供了与POSIX兼容的库。 Linux的系统调用像大多数Unix系统一样,作为C库的一部分提供 , C库实现了Unix系统的主要API,包括标准C库函数和系统调用。所有的C程序都可以使用C库,而由于C语言本身的特点,其他语言也可以很方便地把它们封装起来使用。此外,C库提供了POSIX的绝大部分API。 图5-1 调用printf()函数时,应用程序、C库和内核之间的关系 从程序员的角度看,系统调用无关紧要;他们只需要跟API打交道就可以了。相反,内核只跟系统调用打交道;库函数及应用程序是怎么使用系统调用不是内核所关心的。 ———这是分割线———– 简单总结: 完成同一功能,不同内核提供的系统调用 (也就是一个函数) 是不同的,例如创建进程,linux下是fork函数,windows下是creatprocess函数。好,我现在在linux下写一个程序,用到fork函数,那么这个程序该怎么往windows上移植?我需要把源代码里的fork通通改成creatprocess,然后重新编译… posix标准的出现就是为了解决这个问题。linux和windows都要实现基本的posix标准,linux把fork函数封装成posix_fork (随便说的) ,windows把creatprocess函数也封装成posix_fork,都声明在unistd.h里。这样,程序员编写普通应用时候,只用包含unistd.h,调用posix_fork函数,程序就在源代码级别可移植了。 POSIX解决什么问题 POSIX解决什么问题 一般情况下,应用程序通过应用编程接口(API)而不是直接通过系统调用来编程(即并不需要和内核提供的系统调用来编程)。一个API定义了一组应用程序使用的编程接口。它们可以实现成调用一个系统,也可以通过调用多个系统来实现,而完全不使用任何系统调用也不存在问题。实际上,API可以在各种不同的操作系统上实现给应用程序提供完全相同的接口,而它们本身在这些系统上的实现却可能迥异。如下图,当应用程序调用printf()函数时,printf函数会调用C库中的printf,继而调用C库中的write,C库最后调用内核的write()。 应用程序、C库和内核之间的关系 从程序员的角度看,系统调用无关紧要,只需要跟API打交道。相反,内核只跟系统调用打交道,库函数及应用程序是怎么系统调用不是内核所关心的。 完成同一功能,不同内核提供的系统调用 (一个函数) 是不同的,例如创建进程,linux下是fork函数,windows下是creatprocess函数。好,我现在在linux下写一个程序,用到fork函数,那么这个程序该怎么往windows上移植?我需要把源代码里的fork通通改成creatprocess,然后重新编译… 主流的操作系统有两种,一种是Windows系统,另一种是Linux系统。由于操作系统的不同,API又分为Windows API和Linux API。在Windows平台开发出来的软件在Linux上无法运行,在Linux上开发的软件在Windows上又无法运行,这就导致了软件移植困难,POSIX(Protabl Operation System 可移植操作系统规范)应运而生。 posix标准的出现就是为了解决这个问题。linux和windows都要实现基本的posix标准,linux把fork函数封装成posix_fork (随便说的) ,windows把creatprocess函数也封装成posix_fork,都声明在unistd.h里。这样,程序员编写普通应用时候,只用包含unistd.h,调用posix_fork函数,程序就在源代码级别可移植了。 posix 是什么? 可移植操作系统接口Portable Operating System Interface of UNIX,POSIX标准定义了操作系统应该为应用程序提供的接口标准,是IEEE为要在各种UNIX操作系统上运行的软件而定义的一系列API标准的总称。 系统调用 (OS call) 系统调用,我们可以理解是操作系统为用户提供的一系列操作的接口 (API) ,这些接口提供了对系统硬件设备功能的操作。这么说可能会比较抽象,举个例子,我们最熟悉的 hello world 程序会在屏幕上打印出信息。程序中调用了 printf() 函数,而库函数 printf 本质上是调用了系统调用 write() 函数,实现了终端信息的打印功能。 ...

2014-12-01 · 2 min · 225 words · -

dotnet

dotnet dotnet-sdk-8.0 (开发工具) ├── dotnet-runtime-8.0 (运行时) ├── dotnet-targeting-pack-8.0 (编译支持) ├── dotnet-templates-8.0 (模板) ├── dotnet-apphost-pack-8.0 (发布支持) └── dotnet-host-8.0 (主机) └── dotnet-hostfxr-8.0 (解析器) # 1. 下载并安装Microsoft GPG密钥和仓库配置 wget https://packages.microsoft.com/config/ubuntu/24.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb # wget https://packages.microsoft.com/config/ubuntu/20.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb sudo dpkg -i packages-microsoft-prod.deb rm packages-microsoft-prod.deb # 2. 更新包列表 sudo apt update # 3. 安装.NET 7.0 SDK sudo apt install dotnet-sdk-7.0 ### ------------------------------- sudo dpkg -i packages-microsoft-prod.deb sudo apt-get install -y dotnet-sdk-7.0 sudo apt-get update && sudo apt-get install -y apt-transport-https dotnet --version dotnet --info apt-cache policy dotnet-sdk-8.0 sudo apt install dotnet-sdk-7.0 -y dotnet --list-runtimes dotnet build --verbosity minimal dotnet run --dry-run

2014-11-29 · 1 min · 96 words · -

Java Callable, Future 和 FutureTask

Java Callable, Future 和 FutureTask 创建线程有两种方式,一种是直接继承 Thread,另外一种就是实现 Runnable 接口。 这两种方式都有一个缺陷就是: 在执行完任务之后无法获取执行结果。 如果需要获取执行结果,就必须通过共享变量或者使用线程通信的方式来达到效果,这样使用起来就比较麻烦。 而自从Java 1.5 开始,JDK 提供了 Callable 和 Future, 通过它们可以在任务执行完毕之后得到任务执行结果。 今天我们就来讨论一下 Callable、Future 和 FutureTask 三个类的使用方法。以下是本文的目录大纲: Callable 与 Runnable Future FutureTask 使用示例 Callable 与 Runnable java.lang.Runnable 是一个接口,里面只声明了一个 run() 方法 public interface Runnable { public abstract void run(); } 由于run()方法返回值为void类型,所以在执行完任务之后无法返回任何结果。 Callable 位于 java.util.concurrent 包下,它也是一个接口,在它里面也只声明了一个方法,只不过这个方法叫做 call(): public interface Callable<V> { V call() throws Exception; } 可以看到,这是一个泛型接口,call()函数返回的类型就是传递进来的V类型。 那么怎么使用 Callable 呢? 一般情况下是配合 ExecutorService 来使用的,在 ExecutorService 接口中声明了若干个 submit 方法的重载版本: ...

2014-11-26 · 2 min · 396 words · -

Java assert

Java assert http://lavasoft.blog.51cto.com/62575/43735 一、概述 在C和C++语言中都有assert关键,表示断言。 在Java中,同样也有assert关键字,表示断言,用法和含义都差不多。 二、语法 在Java中,assert关键字是从JAVA SE 1.4 引入的,为了避免和老版本的Java代码中使用了assert关键字导致错误,Java在执行的时候默认是不启动断言检查的 (这个时候,所有的断言语句都将忽略!) ,如果要开启断言检查,则需要用开关-enableassertions或-ea来开启。 assert关键字语法很简单,有两种用法: assert <boolean表达式> 如果<boolean表达式>为true,则程序继续执行。 如果为false,则程序抛出AssertionError,并终止执行。 assert <boolean表达式> : <错误信息表达式> 如果<boolean表达式>为true,则程序继续执行。 如果为false,则程序抛出java.lang.AssertionError,并输入<错误信息表达式>。 三、应用实例 下面给出一个例子,通过例子说明其用法: public class AssertFoo { public static void main(String args[]) { //断言1结果为true,则继续往下执行 assert true; System.out.println(“断言1没有问题,Go!”); System.out.println("\n-----------------\n"); //断言2结果为false,程序终止 assert false : "断言失败,此表达式的信息将会在抛出异常的时候输出!"; System.out.println("断言2没有问题,Go!"); } } 保存代码到C:\AssertFoo.java,然后按照下面的方式执行,查看控制台输出结果: 编译程序: C:>javac AssertFoo.java 默认执行程序,没有开启-ea开关: C:>java AssertFoo 断言1没有问题,Go! 断言2没有问题,Go! 开启-ea开关,执行程序: C:>java -ea AssertFoo 断言1没有问题,Go! Exception in thread “main” java.lang.AssertionError: 断言失败,此表达式的信息将 会在抛出异常的时候输出! at AssertFoo.main(AssertFoo.java:10) ...

2014-11-26 · 1 min · 85 words · -

mutex, 锁

mutex, 锁 Mutual exclusion (或者锁) 的实现有硬件实现和软件实现, 软件实现是通过一些特别的算法譬如 Peterson’s algorithm,这类软件实现通常比硬件实现需要更多的内存,而且由于现代计算机的乱序执行,需要手动加memory barrier来保证memory ordering,这里暂时不做讨论纯软件实现。CPU如果提供一些用来构建锁的atomic指令,一般会更高效一些。 锁的本质 所谓的锁,在计算机里本质上就是一块内存空间。当这个空间被赋值为1的时候表示加锁了,被赋值为0的时候表示解锁了,仅此而已。多个线程抢一个锁,就是抢着要把这块内存赋值为1。在一个多核环境里,内存空间是共享的。每个核上各跑一个线程,那如何保证一次只有一个线程成功抢到锁呢?你或许已经猜到了,这必须要硬件的某种 guarantee。具体的实现如下。 硬件 CPU如果提供一些用来构建锁的 atomic 指令, 譬如 x86 的 CMPXCHG (加上LOCK prefix), 能够完成 atomic 的 compare-and-swap (CAS), 用这样的硬件指令就能实现 spin lock. 本质上 LOCK 前缀的作用是锁定系统总线 (或者锁定某一块cache line) 来实现atomicity,可以了解下基础的缓存一致协议譬如MSEI。简单来说就是,如果指令前加了LOCK前缀,就是告诉其他核,一旦我开始执行这个指令了,在我结束这个指令之前,谁也不许动。缓存一致协议在这里面扮演了重要角色,这里先不赘述。这样便实现了一次只能有一个核对同一个内存地址赋值。 操作系统 mutex在linux内核中由 futex 系统调用支撑,如果没有竞争不需要陷入内核;内核的主要是 futex_wait/wake 函数配合上层完成业务逻辑; 一个 spin lock 就是让没有抢到锁的线程不断在 while 里面循环进行 compare-and-swap, 燃烧CPU, 浪费青春, 直到前面的线程放手 (对应的内存被赋值0) 。这个过程不需要操作系统的介入,这是运行程序和硬件之间的故事。如果需要长时间的等待,这样反复CAS轮询就比较浪费资源,这个时候程序可以向操作系统申请被挂起,然后持锁的线程解锁了以后再通知它。这样CPU就可以用来做别的事情,而不是反复轮询。 但是OS切换线程也需要一些开销,所以是否选择被挂起,取决于大概是否需要等很长时间,如果需要,则适合挂起切换为别的线程。线程向操作系统请求被挂起是通过一个系统调用,在linux上的实现就是 futex, 宏观来讲, OS需要一些全局的数据结构来记录一个被挂起线程和对应的锁的映射关系,这样一个数据结构天然是全局的,因为多个OS线程可能同时操作它。所以,实现高效的锁本身也需要锁。有没有一环套一环的感觉?futex的巧妙之处就在于,它知道访问这个全局数据结构不会太耗时,于是futex里面的锁就是spin lock。linux上pthread mutex 的实现就是用的 futex 。更多精彩内存参考talk: https://www.infoq.com/presentations/go-locks/ 用户态的锁 像Goroutine线程就是go runtime来调度的,而不是OS,所以go routine线程切换的开销要远小于OS线程切换的开销。Goroutine的本质就是一个coroutine,这种轻量的线程在很多语言的runtime里面都有实现。最近Java也有了 (project loom) 。 ...

2014-11-19 · 3 min · 484 words · -

java 对象

java 对象 http://www.jianshu.com/p/ebaa1a03c594 Java程序执行时,第一步系统创建虚拟机进程,然后虚拟器用类加载器Class Loader加载java程序类文件到方法区。 方法区放哪些东西? 存放加载过的类信息、常量、静态变量、及jit编译后的代码 (类方法) 等数据的内存区域。它是线程共享的。 方法区存放的信息包括: 类的基本信息、运行时常量池、变量字段信息、方法信息等。这部分的详细介绍看下面链接的文章。 详细Java程序运行的内存结构介绍 点此处 简要过程: 类加载完成后,主线程运行static main () 时在虚拟机栈中建栈帧,压栈。 执行到new Object () 时,在堆heap里创建对象。 对象创建的过程就是堆上分配实例对象内容空间的过程,在堆中对象内存空间的具体结构如下: 对象头 这个头包括两个部分,第一部分用于存储自身运行时的数据例如GC标志位、哈希码、锁状态等信息。第二部分存放指向方法区类静态数据的指针。 实例变量 存放类的属性数据信息,包括父类的属性信息。如果是数组的实例部分还包括数组的长度。这部分内存按4字节对齐。 填充数据 这是因为虚拟机要求对象起始地址必须是8字节的整数倍。填充数据不是必须存在的,仅仅是为了字节对齐。HotSpot VM的自动内存管理要求对象起始地址必须是8字节的整数倍。对象头本身是8的倍数,当对象的实例变量数据不是8的倍数,便需要填充数据来保证8字节的对齐。另外,堆上对象内存的分配是并发进行的. 然后执行类的构造函数初始化。 Java虚拟机规范规定该区域可抛出OutOfMemoryError。 详细步骤 例如: Dog dog= new Dog(); 当虚拟机执行到new指令时,它先在常量池中查找"Dog",看能否定位到Dog类的符号引用;如果能,说明这个类已经被加载到方法区了,则继续执行。如果没有,就让Class Loader先执行类的加载。 然后,虚拟机开始为该对象分配内存,对象所需要的内存大小在类加载完成后就已经确定了。这时候只要在堆中按需求分配空间即可。具体分配内存时有两种方式,第一种,内存绝对规整,那么只要在被占用内存和空闲内存间放置指针即可,每次分配空间时只要把指针向空闲内存空间移动相应距离即可,当某对象被GC回收后,则需要进行某些对象内存的迁移。第二种,空闲内存和非空闲内存夹杂在一起,那么就需要用一个列表来记录堆内存的使用情况,然后按需分配内存。 对于多线程的情况,如何确保一个线程分配了对象内存但尚未修改内存管理指针时,其他线程又分配该块内存而覆盖的情况?有一种方法,就是让每一个线程在堆中先预分配一小块内存 (TLAB本地线程分配缓冲) ,每个线程只在自己的内存中分配内存。但对象本身按其访问属性是可以线程共享访问的。 内存分配到后,虚拟机将分配的内存空间都初始化为零值(不包括对象头)。实例变量按变量类型初始化相应的默认值 (数值型为0,boolan为false) ,所以实例变量不赋初值也能使用。接着设置对象头信息,比如对象的哈希值,GC分代年龄等。 从虚拟机角度,此时一个新的对象已经创建完成了。但从我们程序运行的角度,新建对象才刚刚开始,对象的构造方法还没有执行。只有执行完构造方法,按构造方法进行初始化后,对象才是彻底创建完成了。 构造函数的执行还涉及到调用父类构造器,如果没有显式声明调用父类构造器,则自动添加默认构造器。 到此,new运算符可以返回堆中这个对象的引用了。 此刻,会根据dog这个变量是实例变量、局部变量或静态变量的不同将引用放在不同的地方: 如果dog局部变量,dog变量在栈帧的局部变量表,这个对象的引用就放在栈帧。 如果dog是实例变量,dog变量在堆中,对象的引用就放在堆。 如果dog是静态变量,dog变量在方法区,对象的引用就放在方法区。 Java有三种方法可以创建对象实例。 new 通常都是使用java的关键字new来创建对象实例。 若有一个Something类,则可以通过下面的语句创建Something类的对象实例并指定到变量obj。 Something something New = new Something(); 通过new创建对象实例必须把类名写在原代码里面。 clone 若程序写成如下,则可以根据当前对象 (this) 建立一个新实例对象 (没有调用构造函数) . ...

2014-11-19 · 2 min · 271 words · -

Chrome 运行Android应用

Chrome 运行Android应用 说到Chrome运行android程序,不得不说一个东西,那就是"Android Runtime for Chrome (ARC) “,ARC是Google最新推出的 Chrome OS 运行Android程序的运行时。ARC基于Google的Native Client(NaCl)功能,其允许通过浏览器来运行原生代码(通常是C或C++),同时具备Chrome所提供的同等安全性。显然,NaCl扩展是可以做到跨平台的,这意味着它能够在PC、Mac、以及Linux等系统的桌面版Chrome浏览器上运行。 但遗憾的是,ARC已经被打上了"Chrome OS专属"的标记,只能运行在Chrome上,并且只能运行Google提供的四款Android App,不能运行其他的。所以一般人无法在桌面版Chrome浏览器上使用。值得庆幸的是,一名叫做 Vladikoff 的黑客,已经突破了这些限制。首先,他实现了如何让Chrome OS能加载任何Android App,而不仅仅局限于官方指定的四款App,而现在,他取得了更大的突破,让Android App工作在Windows,Mac和Linux操作系统当中。 Vladikoff做了一个定制版本的ARC,称之为"ARChon”,可以在Windows,Mac和Linux操作系统当中Chrome37及以上版本的Chrome浏览器中可运行任何Android应用程序,但是,ARC不支持原始的Android应用程序包 (APK) ,它们需要被转换成一个Chrome扩展,好在Vladikoff提供了一个名为chromeos-apk 的转换工具,可以把Apk文件转换成Chrome扩展。 http://my.oschina.net/fants/blog/323672

2014-11-19 · 1 min · 25 words · -

DMA

DMA DMA的基本定义 DMA,全称Direct Memory Access,即直接存储器访问。 DMA传输将数据从一个地址空间复制到另一个地址空间,提供在外设和存储器之间或者存储器和存储器之间的高速数据传输。当CPU初始化这个传输动作,传输动作本身是由DMA控制器来实现和完成的。DMA传输方式无需CPU直接控制传输,也没有中断处理方式那样保留现场和恢复现场过程,通过硬件为RAM和IO设备开辟一条直接传输数据的通道,使得CPU的效率大大提高。 DMA的主要特征 ·每个通道都直接连接专用的硬件DMA请求,每个通道都同样支持软件触发,这些功能通过软件来配置。 ·在同一个DMA模块上,多个请求间的优先权可以通过软件编程设置(共有四级:很高、高、中等和低),优先权设置相等时由硬件决定(请求0优先于请求1,依此类推)。 ·独立数据源和目标数据区的传输宽度(字节、半字、全字),模拟打包和拆包的过程。源和目标地址必须按数据传输宽度对齐。 ·支持循环的缓冲器管理。 ·每个通道都有3个事件标志(DMA半传输、DMA传输完成和DMA传输出错),这3个事件标志逻辑或成为一个单独的中断请求。 ·存储器和存储器间的传输、外设和存储器、存储器和外设之间的传输。 ·闪存、SRAM、外设的SRAM、APB1、APB2和AHB外设均可作为访问的源和目标。 ·可编程的数据传输数目:最大为65535(0xFFFF)。 STM32F411x系列芯片DMA控制器 DMA的工作框图如下图所示。DMA控制器和Cortex™-M4核心共享系统数据总线,执行直接存储器数据传输。当CPU和DMA同时访问相同的目标(RAM或外设)时,DMA请求会暂停CPU访问系统总线达若干个周期,总线仲裁器执行循环调度,以保证CPU至少可以得到一半的系统总线(存储器或外设)带宽。 DMA控制器传输作为AHB主设备操作直接存储器,它可以控制AHB总线的控制矩阵以启动AHB传送。它可以执行以下信息交换: •外设到内存 •内存到外设 •内存到内存 DMA控制器提供两个AHB主端口:AHB内存端口(用于连接到内存)和AHB外设端口(用于连接到外设)。 但是,为了允许内存到内存的传输,AHB外设端口也必须可以访问内存。AHB从端口用于对DMA控制器的编程控制(仅支持32位访问)。 DMA处理 对于两个DMA控制器的系统实现如下图所示。DMA1控制器AHB外设端口没有像DMA2控制器那样连接到总线矩阵,所以只有DMA2能够执行内存到内存的数据传输。 DMA事务由给定数量的数据传输序列组成,可以传输的数据项的数量及其宽度(8位,16位或32位)可以通过软件编程实现。每个DMA传输都包含三个操作步骤: ·从外设数据寄存器或者从当前外设/存储器地址寄存器指示的存储器地址取数据,第一次传输时的开始地址是DMA_CPARx或DMA_CMARx寄存器指定的外设基地址或存储器单元; ·存数据到外设数据寄存器或者当前外设/存储器地址寄存器指示的存储器地址,第一次传输时的开始地址是DMA_CPARx或DMA_CMARx寄存器指定的外设基地址或存储器单元; ·执行一次DMA_CNDTRx寄存器的递减操作,该寄存器包含未完成的操作数目。 通道选择 事件发生后,外设向DMA控制器发送请求信号,DMA控制器根据通道优先级来处理请求。当DMA控制器访问外围设备时,确认信号即由DMA控制器发送到外围设备,一旦外围设备从DMA控制器收到确认信号,它就会释放其请求,当外设取消了该请求后,DMA控制器将释放确认信号。 如果外设还有更多请求,它可以启动下一轮请求操作。 每个数据流流都与一个DMA请求相关,该DMA请求可以从8个可能的通道请求中选择,由DMA_SxCR寄存器中的CHSEL [2:0]位控制。 来自外设(TIM,ADC,SPI,I2C等)的8个请求独立连接到每个通道如下图所示: 仲裁器 仲裁器根据通道请求的优先级来启动外设/存储器的访问。优先权管理分2个阶段: ·软件:每个通道的优先权可以在DMA_CCRx寄存器中设置,有4个等级:最高优先级、高优先级、中等优先级、低优先级; ·硬件:如果2个请求有相同的软件优先级,则较低编号的通道比较高编号的通道有较高的优先权。比如:如果软件优先级相同,通道2优先于通道4。 注意: 在大容量产品和互联型产品中,DMA1控制器拥有高于DMA2控制器的优先级。 DMA通道数据量 每个通道都可以在有固定地址的外设寄存器和存储器地址之间执行DMA传输。DMA传输的数据量是可编程的,最大达到65535(0xFFFF)。包含要传输的数据项数量的寄存器,在每次传输后递减。外设和存储器的传输数据量可以通过DMA_CCRx寄存器中的PSIZE和MSIZE位编程得到。 DMA传输模式 数据传输源和目的地都可以寻址整个4 GB区域中的外围设备和存储器,其地址介于0x0000 0000和0xFFFF FFFF之间。传输方向使用DMA_SxCR寄存器中的DIR [1:0]位进行配置,并提供三种可能性:存储器到外围设备,外围设备到存储器或存储器到存储器的传输。 外设到存储器模式 使能此模式时(通过将DMA_SxCR寄存器中的EN位置1),每次发生外设请求时,数据流都会启动传输从数据源来填充到FIFO。当达到FIFO的阈值水平时,FIFO的内容被清空并存储到目标地址。 当外设请求结束传输时(对于外设流控制器),或当DMA_SxNDTR寄存器达到零时或将DMA_SxNDTR寄存器中的EN位清零,则传输停止。 当赢得了相应流的仲裁时,该数据流通道才可以访问AHB源或目标端口,使用DMA_SxCR寄存器中的PL [1:0]位,为每个数据流通道的优先级进行仲裁。 存储器到外设模式 使能该模式时(通过将DMA_SxCR寄存器中的EN位置1),该数据流通道立即启动传输,以完全填充FIFO。每次发生外设请求时,FIFO的内容都会被清空并存储到目的地。当FIFO未满时,会从内存中重新加载数据。 当外设请求结束传输时(对于外设流控制器),或者当DMA_SxNDTR寄存器达到零时或将DMA_SxNDTR寄存器中的EN位清零,则传输停止。 当赢得了相应流的仲裁时,该数据流通道才可以访问AHB源或目标端口,使用DMA_SxCR寄存器中的PL [1:0]位,为每个数据流通道的优先级进行仲裁。 存储器到存储器模式 配置同上。存储器到存储器模式不能与循环模式同时使用。 循环模式 循环模式可用于处理循环缓冲区和连续数据流(例如ADC扫描模式)。 可以使用DMA_SxCR寄存器中的CIRC位来启用此功能。使能循环模式后,将在数据流通道配置阶段使用初始值自动装载要传输的数据,并且DMA请求将继续。 中断 每个DMA通道都可以在DMA传输过半、传输完成和传输错误时产生中断。为应用的灵活性考虑,通过设置寄存器的不同位来打开这些中断。 对于每个DMA数据流通道,可以在以下事件上产生中断: •达到半转移 •转移完成 •传输错误 ...

2014-11-17 · 1 min · 171 words · -

semaphore/信号量, mutex/互斥锁

信号量 Semaphore 信号量是 Edsger Dijkstra 发明的数据结构,在解决多种同步问题时很有用。其本质是一个整数,并关联两个操作: 申请 acquire(也称为 wait、decrement 或 P 操作) 释放 release(也称 signal、increment 或 V 操作) acquire操作将信号量减 1,如果结果值为负则线程阻塞,且直到其他线程进行了信号量累加为正数才能恢复。如结果为正数,线程则继续执行。 release操作将信号量加 1,如存在被阻塞的线程,此时他们中的一个线程将解除阻塞。 Go 运行时提供的 runtime_SemacquireMutex 和runtime_Semrelease 函数可用来实现sync.RWMutex互斥锁。 semaphore/信号量, mutex/互斥锁 Mutex 是一把钥匙,一个人拿了就可进入一个房间,出来的时候把钥匙交给队列的第一个。一般的用法是用于串行化对 critical section 代码的访问,保证这段代码不会被并行的运行。 Semaphore/信号量 是一件可以容纳 N 人的房间,如果人不满就可以进去,如果人满了, 就要等待有人出来. 对于N=1的情况,称为binary semaphore。一般的用法是,用于限制对于某一资源的同时访问。 Binary semaphore 与 Mutex 的差异 在 有的系统中 Binary semaphore 与 Mutex 是没有差异的。在有的系统上,主要的差异是mutex一定要由获得锁的进程来释放。而semaphore可以由其它进程释放 (这时的semaphore实际就是个原子的变量,大家可以加或减) ,因此semaphore可以用于进程间同步。Semaphore的同步功能是所有系统都支持的,而Mutex能否由其他进程释放则未定,因此建议mutex只用于保护critical section。而semaphore则用于保护某变量,或者同步。 关于semaphore和mutex的区别,网上有著名的厕所理论 (http://koti.mbnet.fi/niclasw/MutexSemaphore.html) : Mutex Mutex 的发音是 /mjuteks/ ,其含义为互斥(体),这个词是Mutual Exclude的缩写。 Is a key to a toilet. One person can have the key - occupy the toilet - at the time. When finished, the person gives (frees) the key to the next person in the queue. Officially: “Mutexes are typically used to serialise access to a section of re-entrant code that cannot be executed concurrently by more than one thread. A mutex object only allows one thread into a controlled section, forcing other threads which attempt to gain access to that section to wait until the first thread has exited from that section.” Ref: Symbian Developer Library(A mutex is really a semaphore with value 1.) ...

2014-10-31 · 5 min · 869 words · -

apktool APK解压、打包

apktool APK解压、打包 keytool -genkey -alias JFrench.keystore -keyalg RSA -validity 1000000 -keystore JFrench.keystore jarsigner -verbose -keystore E:\projects\keystore\JFrench.keystore -s ignedjar JFrench_signed.apk foo.apk JFrench.keystore http://showlike.iteye.com/blog/1686103 http://blog.csdn.net/jesusjzp/article/details/7922451 apktool之APK解压、打包 http://blog.csdn.net/caszhao/article/details/6030425 博客分类: java apktoolandroidjava 简介: Android apktool是一个用来处理APK文件的工具,可以对APK进行反编译生成程序的源代码和图片、XML配置、语言资源等文件,也可以添加新的功能到APK文件中。用该工具来汉化Android软件然后重新打包发布是相当简单的。 安装 .首先安装需要JAVA环境,先下载JDK/JRE,点击下载,已经有JAVA环境的可跳过此步 .到code.google上下载apktool.jar以及相关文件: http://code.google.com/p/android-apktool/downloads/list 点击下载apktool1.4.3.tar.bz2 和 apktool-install-windows-r04-brut1.tar.bz2 .解压apktool-install-windows-r04-brut1.tar.bz2到任意文件夹,然后解压apktool1.4.3.tar.bz2,把apktool.jar拷贝至apktool-install-windows-r04-brut1.tar.bz2解压所在的文件夹下,此时文件下有aapt.exe、apktool.bat及apktool.jar三个应用。 .点击开始菜单,运行,输入CMD回车,用cd命令转到刚刚解压的D:\My Documents\Desktop\apktool-install-windows-r04-brut1所在的文件夹,输入apktool,出现如下命令即说明安装成功 (以下信息,即apktool使用命令) 。 D:\My Documents\Desktop\apktool-install-windows-r04-brut1>apktool Java代码 收藏代码 Apktool v1.4.3 - a tool for reengineering Android apk files Copyright 2010 Ryszard Wi?niewski brut.alll@gmail.com Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0) Usage: apktool [-q|-quiet OR -v|-verbose] COMMAND [...] ...

2014-09-24 · 2 min · 322 words · -

BSc, BA

BSc, BA BA,全称:Bachelor of Arts,文学学士 BSc,全称:Bachelor of Science,理学学士 MA,全称:Master of Arts, 文学硕士 MBA,全称:Master of Business Administration,工商管理硕士 PhD,全称:Doctor of Philosophy, abbreviated as PhD, Ph.D., D.Phil., or DPhil,博士学位 中心思想就是:Doctor of Philosophy 的叫法源自传统,因为古代欧洲除了神学、法律和医学以外的其他学科都被称为哲学。所以,(据我所知),目前大学和研究机构会颁发的博士学位除了哲学博士以外,还有法学博士(Doctor of Laws)和医学博士(Doctor of Medicine)。顺便摘一段,哲学是什么?(依旧维基)哲学是对普遍而基本的问题的研究,这些问题多与实在、存在、知识、价值、理性、心灵、语言、思想等有关。哲学与其他学科的不同之处在于其批判的方式、通常是系统化的方法,并且以理性论证为基础。 作者:董羽流 链接:https://www.zhihu.com/question/26035428/answer/31879134 来源:知乎 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 https://matt.might.net/articles/phd-school-in-pictures/

2014-09-05 · 1 min · 39 words · -

java openjdk JMH

java openjdk JMH create test project with maven mvn archetype:generate \ -DinteractiveMode=false \ -DarchetypeGroupId=org.openjdk.jmh \ -DarchetypeArtifactId=jmh-java-benchmark-archetype \ -DgroupId=org.sample \ -DartifactId=test \ -Dversion=1.0 JMH 是一个由 OpenJDK/Oracle 里面那群开发了 Java 编译器的大牛们所开发的 Micro Benchmark Framework 。何谓 Micro Benchmark 呢?简单地说就是在 method 层面上的 benchmark,精度可以精确到微秒级。可以看出 JMH 主要使用在当你已经找出了热点函数,而需要对热点函数进行进一步的优化时,就可以使用 JMH 对优化的效果进行定量的分析。 比较典型的使用场景还有: 想定量地知道某个函数需要执行多长时间,以及执行时间和输入 n 的相关性 一个函数有两种不同实现 (例如实现 A 使用了 FixedThreadPool,实现 B 使用了 ForkJoinPool) ,不知道哪种实现性能更好 尽管 JMH 是一个相当不错的 Micro Benchmark Framework,但很无奈的是网上能够找到的文档比较少,而官方也没有提供比较详细的文档,对使用造成了一定的障碍。但是有个好消息是官方的 Code Sample 写得非常浅显易懂,推荐在需要详细了解 JMH 的用法时可以通读一遍——本文则会介绍 JMH 最典型的用法和部分常用选项。 第一个例子 如果你使用 maven 来管理你的 Java 项目的话,引入 JMH 是一件很简单的事情——只需要在 pom.xml 里增加 JMH 的依赖即可 <jmh.version>1.14.1</jmh.version> ...

2014-09-03 · 5 min · 866 words · -