java

synchronized&monitor

synchronized、monitor、wait、notify Synchronize是java中解决并发问题比较常用的一种方法。从语法上面来说synchronized总共有三种用法。修饰普通方法,修饰静态方法,和同步代码块。 我们对同步代码块的方法进行反编译,可以发现,在synchronized囊括的代码中分别有monitorenter和monitorexit两个指令。虚拟机规范中对着两个指令如下描述:每个对象都有一个monitor。当monitor被占用的时候就会处于锁定状态。当线程monitorenter指令尝试获取monitor所有权时,如果进入数为0,则该线程进入,将进入数设置为1,该线程几位monitor的所有者。其他的线程在进入的时候就会进入阻塞状态,知道monitor的进入数量为0.而monitorexit会对进入数量减1,当变为0的时候,monitor就不再被这个线程占用。 而对synchronize修饰的方法反编译的时候发现,方法没有在使用monitorenter和monitorexit来实现,但是在方法的flags中acc——synchronized的标志。当调用acc_synchronize标志的方法的时候也会先去获取monitor对象,所以本质上和同步代码块是一样的。 同步代码块的monitor来自指定对象,

  • developer
3 min read
java

java内部类

java静态内部类及非静态内部类 在非静态内部类中不可以声明静态成员变量及方法,静态内部类可声明静态及非静态成员变量及方法 非静态内部类,可以随意的访问外部类中的成员变量与成员方法,即使这些成员方法被修饰为private 不能够从静态内部类的对象中访问外部类的非静态成员(包括成员变量与成员方法) 创建静态内部类时不需要将静态内部类的实例绑定在外部类的实例上,而非静态内部类必须绑定在外部类的实例上 内部类的声明关键字同其它成员变量的声明关键字,如若内部类声明为protected,则当前类,同包,子类可创建及使用该内部类,而其它类则不可访问;内部类中的声明同理 // 非静态内部类 Student s = new Student(); Child c = s.new Child(); // 静态内部类 Student s = new Student(); Child

  • developer
1 min read
java

7.3 jvm之nio之基本概念及基本操作

一. io与nio的区别 io 与 nio介绍 io:io是对流的操作,分input及output两种流。 nio:nio是对缓冲区的操作,该缓冲区为双向的,即可输入又可输出 Java NIO提供了与标准IO不同的IO工作方式: Channels and Buffers(通道和缓冲区):标准的IO基于字节流和字符流进行操作的,而NIO是基于通道(Channel)和缓冲区(Buffer)进行操作,数据总是从通道读取到缓冲区中,或者从缓冲区写入到通道中。 Asynchronous IO(异步IO):Java NIO可以让你异步的使用IO,例如:当线程从通道读取数据到缓冲区时,

  • developer
4 min read
java

7.2 jvm之io字节流

字节输入流 字节输入流概括 值得注意的地方有: Level 2的输入流,大多数都会指明数据源的形式:例如ByteArray,File,Piped Level 3的输入流,则不会出现具体的数据源名字,而是以功能取代:例如Buffered,LineNumber 所以说Level 3的输入流是对Level 2输入流的“封装和过滤”。实际上Level 3的输入流,都继承于FilterInputStream的输入流。 input stream介绍 ByteArrayInputStream 从内存中每次读取一个字节的数据,然后保存到内置的缓冲区中。维持一个计数器用来记录从数据源中读入的字节数目。 调用该输入流的close()方法不会产生任何实际的作用。因为它“关闭”的对象是---内存。

  • developer
4 min read
java

7.1 jvm之io字符流

字符输入流 字符输入流概括 Level 2的输入流,大多数都会指明数据源的形式:例如CharArray,String,File Level 3的输入流,则不会在出现具体的数据源名字,而是以功能取代。例如:Buffered,LineNumber 但是和基于字节的输入流结构不同,FileInputStream是直接继承于InputStream类(基础类)的。但是FileReader却是继承于InputStreamReader的。看看下面的结构: java.io.Reader (implements java.io.Closeable, java.lang.Readable) java.io.

  • developer
5 min read
java

java之AQS

AQS概述 AQS(AbstractQueuedSynchronizer),类如其名,抽象的队列式的同步器,AQS定义了一套多线程访问共享资源的同步器框架,许多同步类实现都依赖于它,如常用的ReentrantLock/Semaphore/CountDownLatch...。 在AQS中维护了一个volatile int state(代表共享资源)和一个FIFO线程等待队列(多线程争用资源被阻塞时会进入此队列) AQS在重入锁中的使用 以ReentrantLock为例,state初始化为0,表示未锁定状态 在ReentrantLock中lock()方法,实际上调用的是AQS的acquire(1)方法;而在acquire(1)中实际上会调用tryAcquire()方法,tryAcquire()方法在AQS中是无方法体的,需要自己实现; unlock(

  • developer
7 min read
java

java垃圾回收算法

标记-清除算法 算法概述 分为标记和清除两个阶段:首先标记出所有需要回收的对象,标记完成后统一回收所有被标记的对象;是最基础的收集算法,其它的收集算法都是基于这种思路并对其不足进行改进而得到的。 不足 效率问题,标记和清除两个过程的效率都不高; 空间问题,标记清除之后会产生大量不连续的内存碎片,空间碎片太多可能会导致以后再程序运行过程中需要分配较大对象时,无法找到足够的连续内存二不得不提前触发另一次垃圾收集动作。 复制算法 算法概述 为了解决效率问题,复制收集算法出现了,他将可用的内存按容量划分为大小相等的两块,每次只使用其中的一块。当这一块内存用完了,就将还存活的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉 不足 这种算法的代价是将内存缩小为原来的一般,代价太高 用途 存活区采用这种算法。因为新生代中的对象98%是“朝生夕死”,所以并不需要按照1:1的比例来划分内存空间,

  • developer
3 min read
java

jvm之Unsafe.CAS

CAS概述 Unsafe 是 java 留给开发者的后门,用于直接操作系统内存且不受 jvm 管辖,实现类似 C++ 风格的操作。 Oracle 官方一般不建议开发者使用 Unsafe 类,因为正如这个类的类名一样,它并不安全,使用不当会造成内存泄露。 在平时的业务开发中,这个类基本是不会有接触到的,但是在 java 的并发包和众多偏向底层的框架中,都有大量应用。 值得一提的是,该类的大部分方法均为 native 修饰,即为直接调用的其它语言(大多为 C++)编写的方法来进行操作,很多细节无法追溯,

  • developer
2 min read
java

JDK动态代理与Cglib动态代理

Cglib与JDK动态代理的区别 JDK代理只能针对实现了接口的类以反射的方式生成代理,而不能针对类 CGLIB是针对类实现代理的,主要对指定的类以字节码转换的方式(ASM框架)生成一个子类,并重写其中的方法。    因为是创建目标类的子类,所以目标类必须要有无参构造函数(子类的有参构造函数会调用父类无参),否则报错 另外因为是继承,所以我们的目标类最好不要使用Final声明 Spring如何切换不同的代理 1、如果目标对象实现了接口,默认会采用JDK的动态代理机制实现AOP,但是可以强制使用CGLIB实现AOP ;     缺点:必须实现接口,并且生成的代理对象也只能声明成为其中一个接口,其他接口的方法和自己的方法访问不到。 2、如果目标对象没有实现接口,必须使用CGLIB生成代理,spring会自动在CGLIB和JDK动态代理之间切换 。 通过注解 @EnableAspectJAutoProxy(proxyTargetClass=true, exposeProxy=true)

  • developer
4 min read
java

7. jvm之io之字符流与字节流总括

1、Java IO 流 io是java中实现输入输出的基础,它可以很方便的完成数据的输入输出操作,Java把不同的输入输出抽象为流,通过流的方式允许Java程序使用相同的方式来访问不同的输入、输出。 2、流的分类 输入流、输出流 A、输入流:只能从中读取数据,而不能向里面写数据 B、 输出流:只能向里面写数据,而不能读数据 可以这样理解,数据从内存到硬盘,通常认为是输出流,即写操作;相反,从硬盘到内存,通常认为是输入流,即读操作;这里的输入、输出是从内存的角度划分的。 Java的输入流主要有InputStream和Reader作为基类,而输出流则主要由OutputStream和Writer作为基类;

  • developer
4 min read
java

18. jvm之关键字

transient:实现Serilizable接口,接口的类均可被实例化,若类的属性以transient标识,则序列化对象的时候,这个属性就不会序列化到指定的目的地中。 native: 调用原生的c语言代码 (4. jvm之native方法和JNI基础中有详细说明) instanceof: instanceof通过返回一个布尔值来指出,这个对象是否是这个特定类或者是它的子类的一个实例。 public static void test(Inter t){   System.err.println(t instanceof InterImpl);   } 注:类 InterImpl必须为Inter的子类(也可以是Inter及其父类,但是对象肯定是Inter及其父类的对象,所以无意义) volatile: http:

  • developer
1 min read
java

17. JVM之性能调优工具

jmap 命令介绍 得到运行java程序的内存分配的详细情况。例如实例个数,大小等 格式 jmap [ option ] pid pid为java进程号 -dump:[live,]format=b,file=<filename> 使用hprof二进制形式,输出jvm的heap内容到文件=. live子选项是可选的,假如指定live选项,那么只输出活的对象到文件. -finalizerinfo 打印正等候回收的对象的信息. -heap 打印heap的概要信息,GC使用的算法,heap的配置及wise heap的使用情况. -histo[:live] 打印每个class的实例数目,

  • developer
8 min read
java

16. jvm之数组

基本数据类型的数组无法自动封装为对象数据类型的数组 数组同样可获取到class对象,通过is.getClass().isArray()判断是否为数组 如果为数组,需要通过args instanceof Object[] 或者 args instanceof int[] 判断是哪种数据类型的数组,之后再进行转换,否则会转换异常 数组包括基本数据类型的数组均通过Object(注意非Object [])入参接收,确定该数组的数据类型后,可转为该类型的数组 Arrays的asList方法只对数据类型为对象类型的数组有效,基本数据类型的数组无效;基本数据类型调用该方法时,会把整个数组当作object放入list中返回 数组的打印结果为[Ljava.lang.String;@5387f9e0,L数组类型;@地址

  • developer
3 min read
java

13. jvm之动态代理

java的动态代理机制详解 在学习Spring的时候,我们知道Spring主要有两大思想,一个是IoC,另一个就是AOP,对于IoC,依赖注入就不用多说了,而对于Spring的核心AOP来说,我们不但要知道怎么通过AOP来满足的我们的功能,我们更需要学习的是其底层是怎么样的一个原理,而AOP的原理就是java的动态代理机制,所以本篇随笔就是对java的动态机制进行一个回顾。 在java的动态代理机制中,有两个重要的类或接口,一个是接口InvocationHandler、另一个则是类 Proxy,这一个类和接口是实现我们动态代理所必须用到的。首先我们先来看看java的API帮助文档是怎么样对这两个类进行描述的: InvocationHandler: InvocationHandler is the interface implemented by the invocation handler of a proxy instance.

  • developer
8 min read
java

11.1. 注解无法通过反射获取到的原因

clazz.getAnnotation(annoClazz); clazz.isAnnotationPresent(annoClazz); 以上代码无法获取到注解,分析原因如下 注解上是否添加了Retention注解,并且value值为RetentionPolicy.RUNTIME Retention注解 Retention(保留)注解说明,这种类型的注解会被保留到那个阶段. 有三个值: RetentionPolicy.SOURCE —— 这种类型的Annotations只在源代码级别保留,编译时就会被忽略 RetentionPolicy.CLASS —— 这种类型的Annotations编译时被保留,在class文件中存在,但JVM将会忽略 RetentionPolicy.RUNTIME —— 这种类型的Annotations将被JVM保留,所以他们能在运行时被JVM或其他使用反射机制的代码所读取和使用. 确保加载注解注释类与注解类的classloader一致,因为判断是否是一个类的标准中包含是否是同一classloader加载的

  • developer
1 min read