Java 获取 进程PID

Java 获取 进程PID String name = ManagementFactory.getRuntimeMXBean().getName(); // get pid String pid = name.split("@")[0]; logger.info("PID:{}", pid); 之前并不知道Java中如何能够获取当前进程 (也就是包含当前Java程序的JVM所在进程) 的进程ID,还以为要通过JNI或者通过Runtime.exec执行shell命令等方式才能获取到当前进程的进程ID,今天在偶然中看到一种在Java程序里,获取当前进程ID的方法,记录下来,以后应该会用到: ) 首先,从JDK1.5之后,Java开始提供包: java.lang.management java.lang.management 提供了一系列的用来在运行时管理和监督JVM和OS的管理接口。 今天我将用到的就是这个包中的一个类: ManagementFactory。 当然,这只是java.lang.management包中的一个小功能,该包还提供了很多其他的管理接口,参照java doc如下: Interface Summary ClassLoadingMXBean The management interface for the class loading system of the Java virtual machine. CompilationMXBean The management interface for the compilation system of the Java virtual machine. GarbageCollectorMXBean The management interface for the garbage collection of the Java virtual machine. ...

2017-03-30 · 1 min · 142 words · -

JVM编译器

JVM编译器 即时编译器 Java虚拟机中内置了两个即时编译器,分别为Client和Server或则叫C1和C2. C1编译器将字节码编译为本地代码,进行简单可靠的优化,C2编译器则会启动一些编译耗时较长的优化,甚至会根据性能监控信息进行一些不可靠的激进优化。C1和C2都是编译一些热点代码 (多次调用的方法或者多次执行的循环体) ,因此在编译前,首先要进行热点探测,HotSpot虚拟机中使用的是基于计数器的热点探测方法。 它为每个方法都准备了两个计数器,方法调用计数器和回边计数器。 方法调用计数器统计的并不是方法被调用的绝对次数,而是一个相对的执行频率,即一段时间内方法被调用的次数。当超过一定的时间限度,如果方法调用次数仍然不足以让它提交给即时编译器,那这个方法的调用计数器就会衰减一般,这个过程称为方法调用计数器热度的衰减。 回边计数器统计的是一个方法中循环体代码执行的次数,它没有热度衰减。建立回边计数器统计的目的是为了处罚OSR编译,OSR即栈上替换,也就是编译发生在方法执行过程之中。 http://blog.csdn.net/tingfeng96/article/details/52261219 http://blog.csdn.net/zhuyijian135757/article/details/38391785 https://cyberdak.github.io/jvm/2017/03/25/jvm-restart-cause-high-load

2017-03-30 · 1 min · 12 words · -

Java Scanner

Java Scanner http://blog.csdn.net/carolzhang8406/article/details/6726589 一、扫描控制台输入 这个例子是常常会用到,但是如果没有Scanner,你写写就知道多难受了。 当通过new Scanner(System.in)创建一个Scanner,控制台会一直等待输入,直到敲回车键结束,把所输入的内容传给Scanner,作为扫描对象。如果要获取输入的内容,则只需要调用Scanner的nextLine()方法即可。 /** 扫描控制台输入 @author leizhimin 2009-7-24 11:24:47 */ public class TestScanner { public static void main(String[] args) { Scanner s = new Scanner(System.in); System.out.println(“请输入字符串: “); while (true) { String line = s.nextLine(); if (line.equals(“exit”)) break; System.out.println("»>” + line); } } } 请输入字符串: 234 wer wer bye bye exit Process finished with exit code 0 先写这里吧,有空再继续完善。 二、如果说Scanner使用简便,不如说Scanner的构造器支持多种方式,构建Scanner的对象很方便。 可以从字符串 (Readable) 、输入流、文件等等来直接构建Scanner对象,有了Scanner了,就可以逐段 (根据正则分隔式) 来扫描整个文本,并对扫描后的结果做想要的处理。 三、Scanner默认使用空格作为分割符来分隔文本,但允许你指定新的分隔符 使用默认的空格分隔符: public static void main(String[] args) throws FileNotFoundException { ...

2017-03-30 · 2 min · 269 words · -

pthread

pthread code #include <pthread.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> void* xc(void* arg){ char* c=(char*)arg; printf("参数%s \n",c); int i=0; for (;i<10;i++){ printf("循环%d\n",i); if(i==5){ pthread_exit(1090000000); } } return 100000222; } void main(){ pthread_t tid; pthread_create(&tid,NULL,xc,"线程!!!!"); void *status; pthread_join(tid,&status); printf("返回%d\n",(int)status); } pthread_create pthread.h是UNIX环境创建线程函数头文件 #include<pthread.h> int pthread_create(pthread_t *restrict tidp,const pthread_attr_t *restrict_attr,void * ( *start_rtn)(void *),void *restrict arg); extern int pthread_create (pthread_t *__restrict __newthread, const pthread_attr_t *__restrict __attr, void *(*__start_routine) (void *), void *__restrict __arg) __THROWNL __nonnull ((1, 3)); 若成功则返回0,否则返回出错编号 返回成功时,由 __newthread 指向的内存单元被设置为新创建线程的线程ID。 __attr 参数用于制定各种不同的线程属性。新创建的线程从start_rtn函数的地址开始运行,该函数只有一个万能指针参数arg,如果需要向start_rtn函数传递的参数不止一个,那么需要把这些参数放到一个结构中,然后把这个结构的地址作为arg的参数传入。 linux下用C开发多线程程序,Linux系统下的多线程遵循POSIX线程接口,称为pthread。 由 restrict 修饰的指针是最初唯一对指针所指向的对象进行存取的方法,仅当第二个指针基于第一个时,才能对对象进行存取。对对象的存取都限定于基于由 restrict 修饰的指针表达式中。 由 restrict 修饰的指针主要用于函数形参,或指向由 malloc() 分配的内存空间。restrict 数据类型不改变程序的语义。 编译器能通过作出 restrict 修饰的指针是存取对象的唯一方法的假设,更好地优化某些类型的例程。参数 第一个参数为指向线程标识符的指针。 第二个参数用来设置线程属性。 第三个参数是线程运行函数的起始地址。 最后一个参数是运行函数的参数。 另外,在编译时注意加上-lpthread参数,以调用静态链接库。因为pthread并非Linux系统的默认库示例 打印线程 IDs #include <pthread.h> ...

2017-03-26 · 2 min · 315 words · -

多线程的代价及上下文切换

多线程的代价及上下文切换 http://www.cnblogs.com/shangxiaofei/p/5762895.html 关于时间, 创建线程使用是直接向系统申请资源的, 这里调用系统函数进行分配资源的话耗时不好说。 关于资源, Java线程的线程栈所占用的内存是在Java堆外的, 所以是不受java程序控制的, 只受系统资源限制, 默认一个线程的线程栈大小是1M (当让这个可以通过设置-Xss属性设置,但是要注意栈溢出问题), 但是, 如果每个用户请求都新建线程的话, 1024个用户光线程就占用了1个G的内存, 如果系统比较大的话,一下子系统资源就不够用了,最后程序就崩溃了。 对操作系统来说,创建一个线程的代价是十分昂贵的, 需要给它分配内存、列入调度,同时在线程切换的时候还要执行内存换页,CPU 的缓存被 清空,切换回来的时候还要重新从内存中读取信息,破坏了数据的局部性。 http://www.cnblogs.com/ktgu/p/3529144.html 多线程的代价 使用多线程往往可以获得更大的吞吐率和更短的响应时间,但是,使用多线程不一定就比单线程程序跑的快,这取决于我们程序设计者的能力以及应用场景的不同。不要为了多线程而多线程,而应考虑具体的应用场景和开发实力,使用多线程就是希望能够获得更快的处理速度和利用闲置的处理能力,如果没带来任何好处还带来了复杂性和一些定时炸弹,那还傻逼了吗?只有在使用多线程给我们带来的好处远大于我们付出的代价时,才考虑使用多线程,有时候可能引入多线程带来的性能提升抵不过多线程而引入的开销,一个没有经过良好并发设计得程序也可能比使用单线程还更慢。 多线程给我们带来的代价 设计更复杂 多线程程序在访问共享数据的时候往往需要我们很小心的处理,否则就会出现难以发现的BUG,一般地,多线程程序往往比单线程程序设计会更加复杂 (尽管有些单线程处理程序可能比多线程程序要复杂) ,而且错误很难重现 (因为线程调度的无序性,某些bug的出现依赖于某种特定的线程执行时序) 。 增加更多的资源消耗 除了CPU执行上下文切换的消耗以外,线程的执行还将有其他一些资源的消耗,比如:内存同步的开销 (线程需要一些内存在维持线程本地栈,每个线程都有本地独立的栈用以存储线程专用数据) ,上下文切换的开销 (前面已经讲过) ,线程创建和消亡的开销,以及调度的开销 (占用操作系统的一些资源来管理和协调线程) , 我们可以创建100个线程让他们什么都不做,看看他们消耗了多少内存。 上下文切换 线程是由 CPU 进行调度的, CPU 的一个时间片内只执行一个线程上下文内的线程, 当CPU由执行线程 A 切换到执行线程 B 的过程中会发生一些列的操作, 这些操作主要有"保存线程A的执行现场“然后”载入线程B的执行现场",这个过程称之为"上下文切换 (context switch)",这个上下文切换过程并不廉价, 如果没有必要, 应该尽量减少上下文切换的发生。 多数人认为使用多线程一定会比单线程执行速度快,但其实未必,因为多线程应用程序会带来额外的开销和竞争问题,他们都可能会拖慢系统的执行速度。这些因素包括: 对IO设备的竞争,对锁的竞争,以及CPU对线程执行上下文的频繁切换等。 目前流行的 CPU 在同一时间内只能运行一个线程, 超线程的处理器 (包括多核处理器) 可以同一时间运行多个线程, linux 是将多核处理器当作多个单独 CPU 来识别的。 每个进程都会分到 CPU 的时间片来运行, 当某个进程 (线程是轻量级进程,他们是可以并行运行的,并且共享地使用他们所属进程的地址空间资源, 比如: 内存空间或其他资源 ) 当进程用完时间片或者被另一个优先级更高的进程抢占的时候, CPU会将该进程备份到 CPU 的运行队列中, 其他进程被调度在 CPU 上运行,这个进程切换的过程被称作"上下文切换", 过多的上下文切换会造成系统很大的开销。 ...

2017-03-26 · 1 min · 109 words · -

公平锁, 非公平锁

公平锁, 非公平锁 公平锁: 每个线程抢占锁的顺序为先后调用lock方法的顺序依次获取锁,类似于排队吃饭。 非公平锁: 每个线程抢占锁的顺序不定,谁运气好,谁就获取到锁,和调用lock方法的先后顺序无关,类似于堵车时,加塞的那些XXXX。 如果在绝对时间上,先对锁进行获取的请求一定被先满足,那么这个锁是公平的,反之,是不公平的,也就是说等待时间最长的线程最有机会获取锁,也可以说锁的获取是有序的。 公平的锁机制往往没有非公平的效率高,因为公平的获取锁没有考虑到操作系统对线程的调度因素,这样造成JVM对于等待中的线程调度次序和操作系统对线程的调度之间的不匹配。对于锁的快速且重复的获取过程中,连续获取的概率是非常高的,而公平锁会压制这种情况,虽然公平性得以保障,但是响应比却下降了,但是并不是任何场景都是以TPS作为唯一指标的,因为公平锁能够减少"饥饿"发生的概率,等待越久的请求越是能够得到优先满足。 http://www.infoq.com/cn/articles/jdk1.8-abstractqueuedsynchronizer http://www.infoq.com/cn/articles/java8-abstractqueuedsynchronizer AbstractQueuedSynchronizer的介绍和原理分析 https://www.zhihu.com/question/36964449 ReentrantLock(重入锁)以及公平性 http://ifeve.com/reentrantlock-and-fairness/embed/#?secret=sEU18txaRD

2017-03-26 · 1 min · 14 words · -

重排序 Reorder

重排序 Reorder 编译器和处理器可能会对操作做重排序。编译器和处理器在重排序时,会遵守数据依赖性,编译器和处理器不会改变存在数据依赖关系的两个操作的执行顺序。 注意,这里所说的数据依赖性仅针对单个处理器中执行的指令序列和单个线程中执行的操作,不同处理器之间和不同线程之间的数据依赖性不被编译器和处理器考虑。 http://www.infoq.com/cn/articles/java-memory-model-2 http://tech.meituan.com/java-memory-reordering.html

2017-03-26 · 1 min · 6 words · -

Java ReentrantLock, synchronized

Java ReentrantLock, synchronized http://www.ibm.com/developerworks/cn/java/j-jtp10264/index.html 多线程和并发性并不是什么新内容,但是 Java 语言设计中的创新之一就是,它是第一个直接把跨平台线程模型和正规的内存模型集成到语言中的主流语言。核心类库包含一个 Thread 类,可以用它来构建、启动和操纵线程,Java 语言包括了跨线程传达并发性约束的构造 - synchronized 和 volatile. 在简化与平台无关的并发类的开发的同时,它决没有使并发类的编写工作变得更繁琐,只是使它变得更容易了。 synchronized 快速回顾 把代码块声明为 synchronized,有两个重要后果, 通常是指该代码具有 原子性 (atomicity) 和 可见性 (visibility) 。 原子性意味着一个线程一次只能执行由一个指定监控对象 (lock) 保护的代码,从而防止多个线程在更新共享状态时相互冲突。 可见性则更为微妙;它要对付内存缓存和编译器优化的各种反常行为。一般来说,线程以某种不必让其他线程立即可以看到的方式 (不管这些线程在寄存器中、在处理器特定的缓存中,还是通过指令重排或者其他编译器优化) ,不受缓存变量值的约束,但是如果开发人员使用了同步,如下面的代码所示,那么运行库将确保某一线程对变量所做的更新先于对现有synchronized 块所进行的更新,当进入由同一监控器 (lock) 保护的另一个 synchronized 块时,将立刻可以看到这些对变量所做的更新。类似的规则也存在于 volatile 变量上。 synchronized (lockObject) { // update object state } 所以,实现同步操作需要考虑安全更新多个共享变量所需的一切,不能有争用条件, 不能破坏数据 (假设同步的边界位置正确) ,而且要保证正确同步的其他线程可以看到这些变量的最新值。通过定义一个清晰的、跨平台的内存模型 (该模型在 JDK 5.0 中做了修改,改正了原来定义中的某些错误) ,通过遵守下面这个简单规则,构建"一次编写,随处运行"的并发类是有可能的: 不论什么时候,只要您将编写的变量接下来可能被另一个线程读取,或者您将读取的变量最后是被另一个线程写入的,那么您必须进行同步。 不过现在好了一点,在最近的 JVM 中,没有争用的同步 (一个线程拥有锁的时候,没有其他线程企图获得锁) 的性能成本还是很低的。 (也不总是这样;早期 JVM 中的同步还没有优化,所以让很多人都这样认为,但是现在这变成了一种误解,人们认为不管是不是争用,同步都有很高的性能成本。) 对 synchronized 的改进 如此看来同步相当好了,是么?那么为什么 JSR 166 小组花了这么多时间来开发 java.util.concurrent.lock 框架呢? 答案很简单-同步是不错,但它并不完美。它有一些功能性的限制 —— 它无法中断一个正在等候获得锁的线程,也无法通过投票得到锁,如果不想等下去,也就没法得到锁。同步还要求锁的释放只能在与获得锁所在的堆栈帧相同的堆栈帧中进行,多数情况下,这没问题 (而且与异常处理交互得很好) ,但是,确实存在一些非块结构的锁定更合适的情况。 ...

2017-03-26 · 13 min · 2754 words · -

cp command

cp command # 把 dir0 下面的文件和子目录复制到 dir1 # -R, -r, --recursive copy directories recursively cp -r /path/to/dir0/* /path/to/dir1

2017-03-25 · 1 min · 18 words · -

通过枚举enum实现单例设计

通过枚举enum实现单例设计 默认枚举实例的创建是线程安全的 通过enum关键字来实现枚举,在枚举中需要注意的有: 枚举中的属性必须放在最前面,一般使用大写字母表示 枚举中可以和java类一样定义方法 枚举中的构造方法必须是私有的 通过一个java类来模拟枚举的功能: package org.lkl.imitate_enum; public abstract class WeekDay { public static final WeekDay SUN = new WeekDay() { @Override public WeekDay nextDay() { return MON; } }; public static final WeekDay MON = new WeekDay() { @Override public WeekDay nextDay() { return SUN; } }; @Override public String toString() { return this == SUN ?“SUN星期天”:“MON星期一” ; } public abstract WeekDay nextDay(); public static void main(String[] args) { System.out.println(WeekDay.SUN.nextDay()); System.out.println(WeekDay.MON.nextDay()); } } 4.可以在枚举属性后面添加()来调用指定参数的构造方法,添加{}来实现其对应的匿名内部类,例如: package org.lkl.imitate_enum; public enum TrafficLamp { RED(30){ ...

2017-03-25 · 2 min · 413 words · -

java 8 新特性

java 8 新特性 https://www.ibm.com/developerworks/cn/java/j-lo-jdk8newfeature/ http://www.ruanyifeng.com/blog/2012/04/functional_programming.html http://www.jianshu.com/p/5b800057f2d8

2017-03-25 · 1 min · 6 words · -

java 7, jdk 7

java 7, jdk 7 数字文字中的下划线 Java 7的一个特性是数字文字中的下划线。可以在任何数字文字的数字之间放置下划线,如:int,byte,short,float,long,double。在数字文字中使用下划线将它们分成组以获得更好的可读性。 public class UnderscoreNumericLiterals { public static void main(String[] args) { long ccNumber = 1234_5678_9012_3456L; long ssn = 999_99_9999L; float pi = 3.14_15F; long hexadecimalBytes = 0xFF_EC_DE_5E; long hexadecimalWords = 0xCAFE_BABE; long maxOfLong = 0x7fff_ffff_ffff_ffffL; byte byteInBinary = 0b0010_0101; long longInBinary = 0b11010010_01101001_10010100_10010010; int add = 12_3 + 3_2_1; System.out.println("ccNumber="+ccNumber); System.out.println("ssn="+ssn); System.out.println("pi="+pi); System.out.println("hexadecimalBytes="+hexadecimalBytes); System.out.println("hexadecimalWords="+hexadecimalWords); System.out.println("maxOfLong="+maxOfLong); System.out.println("byteInBinary="+byteInBinary); System.out.println("longInBinary="+longInBinary); System.out.println("add="+add); } } https://www.yiibai.com/java/underscores-in-numeric-literals-java-7-feature.html https://www.ibm.com/developerworks/cn/java/j-lo-jdk7-1/ ...

2017-03-25 · 1 min · 70 words · -

wait(),notify(),notifyAll()

wait(),notify(),notifyAll() notifyAll 是一个重的方法,它会带来大量的上下文切换和锁竞争。 wait(),notify(),notifyAll()不属于Thread类,而是属于Object基础类,也就是说每个对像都有wait(),notify(),notifyAll()的功能.因为都个对像都有锁,锁是每个对像的基础,当然操作锁的方法也是最基础了。 wait导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或被其他线程中断。wait只能由持有对像锁的线程来调用。 notify唤醒在此对象监视器上等待的单个线程。如果所有线程都在此对象上等待,则会选择唤醒其中一个线程(随机)。直到当前的线程放弃此对象上的锁,才能继续执行被唤醒的线程。同Wait方法一样,notify只能由持有对像锁的线程来调用.notifyall也一样,不同的是notifyall会唤配所有在此对象锁上等待的线程。 “只能由持有对像锁的线程来调用"说明wait方法与notify方法必须在同步块内执行,即synchronized(obj)之内.再者synchronized代码块内没有锁是寸步不行的,所以线程要继续执行必须获得锁。相辅相成。 看一个很经典的例子(生产者与消费者): package ProductAndConsume; import java.util.List; public class Consume implements Runnable{ private List container = null; private int count; public Consume(List lst){ this.container = lst; } public void run() { while(true){ synchronized (container) { if(container.size()== 0){ try { container.wait();//容器为空,放弃锁,等待生产 } catch (InterruptedException e) { e.printStackTrace(); } } try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } container.remove(0); container.notify(); System.out.println(“我吃了”+(++count)+“个”); } } } } package ProductAndConsume; import java.util.List; public class Product implements Runnable { private List container = null; ...

2017-03-24 · 1 min · 209 words · -

java juc锁 Lock

java juc锁 Lock 与synchronized不同的是,Lock完全用Java写成,在java这个层面是无关JVM实现的。 在java.util.concurrent.locks包中有很多Lock的实现类,常用的有ReentrantLock、ReadWriteLock (实现类ReentrantReadWriteLock) ,其实现都依赖java.util.concurrent.AbstractQueuedSynchronizer类 锁像synchronized同步块一样,是一种线程同步机制,但比Java中的synchronized同步块更复杂。因为锁 (以及其它更高级的线程同步机制) 是由synchronized同步块的方式实现的,所以我们还不能完全摆脱synchronized关键字 (译者注: 这说的是Java 5之前的情况) 。 自Java 5开始,java.util.concurrent.locks包中包含了一些锁的实现,因此你不用去实现自己的锁了。但是你仍然需要去了解怎样使用这些锁,且了解这些实现背后的理论也是很有用处的。可以参考我对java.util.concurrent.locks.Lock的介绍,以了解更多关于锁的信息。 Lock是java.util.concurrent.locks包下的接口,Lock 实现提供了比使用synchronized 方法和语句可获得的更广泛的锁定操作,它能以更优雅的方式处理线程同步问题 //一个简单的锁 public class Counter{ private int count = 0; public int inc(){ synchronized(this){ return ++count; } } } 可以看到在inc()方法中有一个synchronized(this)代码块。该代码块可以保证在同一时间只有一个线程可以执行return ++count。虽然在synchronized的同步块中的代码可以更加复杂,但是++count这种简单的操作已经足以表达出线程同步的意思。 以下的Counter类用Lock代替synchronized达到了同样的目的: public class Counter{ private Lock lock = new Lock(); private int count = 0; public int inc(){ lock.lock(); int newCount = ++count; lock.unlock(); return newCount; } } lock()方法会对Lock实例对象进行加锁,因此所有对该对象调用lock()方法的线程都会被阻塞,直到该Lock对象的unlock()方法被调用。 ...

2017-03-24 · 5 min · 976 words · -

external file changes sync may be slow the current inotify watch limit is too low

’external file changes sync may be slow the current inotify watch limit is too low' http://ggarcia.me/2016/07/12/intellij-inotify-arch.html To fix the warning about fs.inotify.max_user_watches the IntelliJ shows, it is necessary to set a value for the fs.inotify.max_user_watches and then apply the change. Here are the commands necessary to fix the issue on ArchLinux: sudo echo 'fs.inotify.max_user_watches = 524288' >>/usr/lib/sysctl.d/50-default.conf sudo sysctl -p --system More information about this can be found in here and in here. ...

2017-03-09 · 1 min · 74 words · -

golang 包机制

golang 包机制 http://blog.wuxu92.com/golang-package-usage/ 我们都知道Golang中有package的概念。在go源码文件的第一行就是先声明包名: package main 这里的包名是一个标签,不是使用字符串。对于简答的项目可以直接使用main作为包名。 在go的开发中,我们会把所有的项目放到GOPATH/src目录下;与其他语言的项目不同,go的约定是 (当前用户) 所有的所有项目都是放到这个目录;所以这里面会有很多的项目。一般约定使用域名作为一级的目录,比如GOPATH/src/github.com这个目录存放所有从github获取的项目。 golang中的包全名是相对于GOPATH/src/的相对路径加源码文件中的package声明。源码的文件夹目录可以随意组织,可以有多层级目录,比如我打一个项目放在 GOPATH/src/wuxu.bit/example/alg/sort目录下。里面的一个源码文件sort.go如下: package sort import “fmt” func Sort(a []int) { // do some sort things // fmt.Println(…) } 现在另外一个项目要使用这个排序方法,假设那个项目目录是GOPATH/src/wuxu/weather/目录下的main.go文件。那么要在main.go中import排序文件的包,这里要用完整的包名 package main import ( sort “wuxu.bit/example/alg/sort” “fmt” ) func main() { // can use sort.Sort here } 上面使用了import包名的别名。 golang在引入包的时候还有一些tricks: import . “fmt” 这样在调用fmt包的导出方法时可以省略fmt import _ “fmt” 这样引入该包但是不引入该包的导出函数,而是为了使用该导入操作的副作用: 调用包里面的init函数 golang的包机制现在还很简单,尤其还没有官方的包依赖解决方案,希望依赖解决能早日出来。

2017-03-09 · 1 min · 58 words · -

逃逸分析

逃逸分析 http://www.iteye.com/topic/473355 什么是逃逸分析(Escape Analysis)? 在编程语言的编译优化原理中,分析指针动态范围的方法称之为逃逸分析。它跟静态代码分析技术中的指针分析和外形分析类似。 通俗一点讲,当一个对象的指针被多个方法或线程引用时,我们称这个指针发生了逃逸。 而用来分析这种逃逸现象的方法,就称之为逃逸分析。 举个例子: Java代码 class A { public static B b; public void globalVariablePointerEscape() { // 给全局变量赋值,发生逃逸 b = new B(); } public B methodPointerEscape() { // 方法返回值,发生逃逸 return new B(); } public void instancePassPointerEscape() { methodPointerEscape().printClassName(this); // 实例引用传递,发生逃逸 } } class B { public void printClassName(A a) { System.out.println(a.class.getName()); } } 在这个例子中,一共举了3种常见的指针逃逸场景。分别是 全局变量赋值,方法返回值,实例引用传递。 逃逸分析优化JVM原理 我们知道java对象是在堆里分配的,在调用栈中,只保存了对象的指针。 当对象不再使用后,需要依靠GC来遍历引用树并回收内存,如果对象数量较多,将给GC带来较大压力,也间接影响了应用的性能。减少临时对象在堆内分配的数量,无疑是最有效的优化方法。 怎么减少临时对象在堆内的分配数量呢?不可能不实例化对象吧! 场景介绍 其实,在java应用里普遍存在一种场景。一般是在方法体内,声明了一个局部变量,且该变量在方法执行生命周期内未发生逃逸 (在方法体内,未将引用暴露给外面) 。 按照JVM内存分配机制,首先会在堆里创建变量类的实例,然后将返回的对象指针压入调用栈,继续执行。 这是优化前,JVM的处理方式。 ...

2017-03-08 · 1 min · 135 words · -

NoClassDefFoundError, ClassNotFoundException

NoClassDefFoundError, ClassNotFoundException http://wxl24life.iteye.com/blog/1919359 java.lang.NoClassDefFoundError 和 java.lang.ClassNotFoundException 都是 Java 语言定义的标准异常。从异常类的名称看似乎都跟类的定义找不到有关,但是还是有些差异。我们先来看一下 java 规范中对这两个异常的说明: java.lang.NoClassDefFoundError: Thrown if the Java Virtual Machine or a ClassLoader instance tries to load in the definition of a class (as part of a normal method call or as part of creating a new instance using the new expression) and no definition of the class could be found. The searched-for class definition existed when the currently executing class was compiled, but the definition can no longer be found. ...

2017-03-08 · 2 min · 279 words · -

JAVA String.format()

JAVA String.format() flags flags是可选参数,用于控制输出的格式,比如左对齐、金额用逗号隔开。 ‘-’ 在最小宽度内左对齐,不可以与"用0填充"同时使用 ‘+’ 结果总是包括一个符号 ’ ’ 正值前加空格,负值前加负号 ‘0’ 结果将用零来填充 ‘,’ 每3位数字之间用",“分隔(只适用于fgG的转换) ‘(’ 若参数是负数,则结果中不添加负号而是用圆括号把数字括起来(只适用于eEfgG的转换) /** flags 的标识 */ private static void formatFlags() { System.out.println(”’-’:在最小宽度内左对齐,不可与"用0填充"同时使用。"); System.out.println(String.format(“设置最小宽度为8为,左对齐。%-8d:%-8d:%-8d%n”, 1, 22, 99999999)); System.out.println(String.format("‘0’:结果将用零来填充。设置最小宽度为8,%08d:%08d:%08d", 1, -22, 99999990)); System.out.println(String.format("’+’:结果总是包括一个符号。%+d:%+d:%+d", 1, -2, 0)); System.out.println(String.format("’ ‘:正值前加空格,负值前加负号。% d:% d:% d", 1, -2, 0)); System.out.println(String.format("’,’:每3位数字之间用",“分隔(只适用于fgG的转换)。%,d:%,d:%,d”, 1, 100, 1000)); System.out.println(String.format("’(’:若参数是负数,则结果中不添加负号而是用圆括号把数字括起来(只适用于eEfgG的转换)。%(d:%(d", 1, -1)); } 输出如下: ‘-’:在最小宽度内左对齐,不可与"用0填充"同时使用。 设置最小宽度为8为,左对齐。1 :22 :99999999 ‘0’:结果将用零来填充。设置最小宽度为8,00000001:-0000022:99999990 ‘+’:结果总是包括一个符号。+1:-2:+0 ’ ‘:正值前加空格,负值前加负号。 1:-2: 0 ‘,’:每3位数字之间用",“分隔(只适用于fgG的转换)。1:100:1,000 ‘(’:若参数是负数,则结果中不添加负号而是用圆括号把数字括起来(只适用于eEfgG的转换)。1:(1) width width是可选参数,用于控制输出的宽度。示例如下: System.out.println(String.format(“设置最小宽度为8,不满8位用0填充: %08d:%08d”, 1, -10000000)); ...

2017-03-02 · 4 min · 713 words · -

systemd-networkd

systemd-networkd dhcp networkd 内置了 dhcp client。 如果需要更新 resolv.conf, 需要启动 systemd-resolved.service 配置文件存放在 /usr/lib/systemd/network (上游提供的配置) /run/systemd/network (运行时配置) /etc/systemd/network (本地配置) 其中 /etc/systemd/network 优先级最高 networkd 有三类配置文件 .link 文件: 当一个网络设备出现时, udev 会寻找第一个匹配到的 .link 文件. .network 文件: 给匹配到的设备应用一个网络配置 .netdev 文件: 给匹配到的环境创建一个虚拟的网络设备 他们都遵循一些相同的规则 如果 [Match] 部分满足了条件, 在接下来的段落中的配置会被应用 [Match] 部分可以接受不止一项条目. 在这种情况下, 只有当每一个条目都被满足时, 这个配置才会被启用 空白的 [Match] 部分表示这个配置在任何情况下都会被应用 每一项条目都是 KEY=VALUE 格式的键值对 所有的配置文件会被收集并按字典序排序后再处理, 无论它们在哪个目录 相同名字的配置文件会相互替代 .network 配置 [Match] Name= 设备名 (比如Br0, enp4s0, 也可以用通配符, 比如 en*), 可以配置多个 name Host= 匹配的 hostname Virtualization= 一个布尔值, 检测你的系统是否运行在一个虚拟化环境中. 也就是说, Virtualization=no 只会在宿主机上满足, 而 Virtualization=yes 会应用到任何虚拟机或 container. [Link] #当 "RequiredForOnline=no" 时, 如果此网络不在线(例如未能从 DHCP 获取IP地址、或者网线被拔出等原因), 那么 "systemd-networkd-wait-online" 将会自动跳过它。 # routable, make routing on this interface a dependency for network-online.target RequiredForOnline=no [Network] DHCP= 一个布尔值. 设为 true 的时候, 会启用 systemd-networkd 自带的基础 DHCPv4 支持. DNS= DNS 服务器地址. Bridge= 如果要将这个连接加入网桥, 在这里写入目标网桥的名字 Address= 静态的 IPv4 或者 IPv6 地址, 以及相应的用/<数字>方式表示的掩码(如 192.168.1.90/24). Gateway= 网关地址. 如果需要指定多个 DNS, Address 或者 Gateway, 你可以多次指定相应的键值对. (也就是说, 多写几行 DNS=xxx, DNS=yyy…) ...

2017-02-28 · 2 min · 319 words · -