- gradle使用
- jvm
gradle使用
gradle是一种自动构建化语言,目前是android的默认构建工具,是一个编程框架
一些使用命令:
gradlew clean clean项目
gradlew build 构建项目
gradlew assembleDebug or gradlew aD 编译并打包Debug包
gradlew assembleRelease or gradlew aR 编译并打release包
gradlew installRelease or gradlew iR release模式打包并安装
gradlew installDebug or gradlew iD Debug模式打包并安装
gradlew uninstallRelease or gradlew uR 卸载Release模式包
gradlew uninstallDebug or gradlew uD 卸载Debug模式包
需要说明的是,有些可以叠加使用
gradlew clean build —info > bugTags.log
grooxy语言
def 关键字:返回值
String: 分两种类型 groovy.lang.GString , java.lang.String
List: 定义 def value = [“a”,”c”, “b”]; value[0] = 4; 默认是ArrayList
如果需要 LinkedList value = []; 这样就强制为了 LinkedList了
Map: def value = [“a”: “str”, “b”: 1] 这里的map是个 []的,不是 {}
Range:范围值
metaClass: 在groovy运行期间使用metaClass添加方法和属性
闭包:
1
2
3
4
5
6>def listener = ({ -> println("click on") })
>演变成:
>def listener = { -> println("click on") }
>def listener = ({ println("click on") })
>再演变:
>def listener = { println("click on") }gradle的执行流程
- 初始化界面:解析settings.gradle来获取模块信息
- 配置阶段:配置每个模块,构建task树
- 执行阶段:执行任务
project相关的api
getRootProject: 获取根project
getAllProjects:获取所有Project
getSubProjects:获取所有的子project
allProjects:遍历所有的project
subprojects:遍历所有子project
属性相关的API
hasProperty:检测属性是否存在
findProperty:查找属性
自定义property:
命令行定义属性 : gradle build -P pro = 100
通过project.ext定义参数
1
2
3
4
5ext.a = 1
或者:
ext {
a = 1
}
task相关的api
- getTasks: 获取当前project所有task
- task 创建一个task、
文件相关的API
- file: 获取文件
- fileTree: 获取文件夹
- getBuildDir:获取build文件夹
gradle生命周期API
beforeEvaluate: 配置阶段开始之前
afterEvaluate: 配置阶段结束
当走到这里,所有的task的配置都已经完成,然后可以在这里加入自定义的task
gradle.buildFinished:执行阶段结束
其它api
执行外部命令
exec:执行外部命令;是project中的
mac的执行
1
2
3
4>project.exec {
executable 'bash'
args '-c', cmd
>}windows执行方式
1
2
3
4>project.exec {
executable 'cmd'
args '/c', cmd
>}
Task
gradle很重要的一个东西
task定义
task myTask {
println “myTask”
}
最后一个参数是闭包,所以这里省略了圆括号
可以通过下面方式创建
project.tasks.create(name: “myTask”) {
println “myTask”
}
task的基本信息配置
1
2
3
4
5
6
7task MyTask (a: "a", b: "b") {println "$a和$b"}
或者
task MyTask {
a "a"
b "b"
println "$a和$b"
}
Task依赖
1
2
3
4
5
6task A{
}
task b {
dependsOn A
}我们需要执行b的时候会先执行A,然后再执行b
task执行
1
2
3
4
5
6
7
8
9
10task myTask {
println "1"
doFirst {
println "2"
}
doLast {
println "3"
}
}实战自定义plugin
1
todo
JVM
1:虚拟机的发展
go语言去实现jvm是比较简单的
hotSpot VM 目前使用最广的虚拟机; 我的mac上面的sdk用的就是类的
JRockit VM 号称是最快的java虚拟机;
J9 VM ibm公司的
Dalvik VM google给android使用的虚拟机
未来的java技术
模块化
OSGI 模块化
微服务
混合语言 (java , scala)
多核并行 (函数式编程)
丰富的语法
64位
更强的垃圾回收 回收 gb级别的, jdk11是gb级别的。
2:内存的划分
线程间共享的:堆和方法区
线程间独享的: 程序计数器,虚拟机栈,本地方法栈
虚拟机栈中有-> 栈帧:局部变量表,返回地址,操作数栈,动态连接
独享就是当线程结束了,内容也随之释放了,没有线程安全问题;共享的话,就引入了锁这些问题,不是线程安全的
程序计数器:指向当前程序的字节码,线程间需要切来切换去,唯一个没有OOM的地方
为什么java要是用栈来进行方法调用:因为非常符合java间方法的调用
javap -v Test.class > 1.txt 然后获取字节码
局部变量表:只能存放32位的数据,放一些方法内部的一些变量,如果是64位,就会使用高低位占用两个也可以存放下来。存放基本类型的变量数据和对象的引用
操作数栈:存放我们方法执行的操作数。它就是一个栈的结构,进行一些数据的计算
动态连接:用来多态使用,java动态运行性,需要类加载运行时,才能确定具体的方法
返回地址:程序正常执行的时候,就会执行到这里,然后返回
本地方法栈:各虚拟机自由实现
线程的共享区域
方法区/永久代
用于存储已经被虚拟机记载的类信息,常量(”123“,”asfda“等),静态变量(static变量)
Jdk7 以及以前: -XX:PermSize: -XX:MaxPermSize;
jdk1.8 以后: -XX:MetaspaceSize: -XX:MaxMetaspaceSize
jdk1.8 以后大小就只受本机总内存的限制
堆
几乎所有的对象都分配在这里,也是垃圾回收发生的主要区域,可用一些参数进行太调整
…
直接内存
不是虚拟机运行时的数据区的一部分,也不是java虚拟机规范中的定义的内存区域;但是受本机总内存限制。也会产生OOM
站在线程的角度来看
线程的私有内存区:随着产生和消亡,因此不要过多考虑内存回收的问题,编译时就确定了所需内存的大小。
深入辨析堆和栈
功能
以栈帧的方式存储方法的调用过程,并存储方法调用过程中基本数据类型的变量,已经对象的应用变量,其内存分配在栈上,变量出了作用域,就会自动释放。
而堆内存用来存储java中的对象,无论成员变量,局部变量,还是类的变量,指向的位置是在堆中。(这个怎么画图,应该是对象模型图???)
线程独显还是共享
栈是属于单个线程所有,相当于线程的私有内存
堆中的所有对象,对所有线程可间。
空间大小
栈的空间远远小于对内存
当栈进行无限制的递归调用的时候,会出现OOM,方法的执行要打包成栈帧,所以天生实现同一个功能的时候要慢,比如树的遍历递归,比较简单,但是比一般的实现要慢,一般的实现代码比较复杂,但是速度快
对象的分配
虚拟机遇到一条new的指令时:
1)检查加载: 先执行相应的类加载过程。
2)分配内存:
指针碰撞:确定一块内存是否能存放下这个对象,如果不能,就继续往下找,找不到就进行垃圾回收了,在eden去就进行mirror Gc 等。这个分配过程就是指针碰撞。
空闲列表:如果java堆中的内存并不规整的,已使用的内存空间相互交错,那就没有办法简单的进行指针碰撞,虚拟机必须维护一个列表,记录那些内存块可以用,那些不可用,在分配的时候从列表中找到一块足够大的空间划分给对象,并更新列表上的几率,这个分配方式称为”空闲列表“。
选择哪种方式由java堆是否规整决定了,还有和采取的算法有关系
并发安全
除如何划分空间外,还要考虑并发安全的问题。
cas操作,如果内存分配失败,会进行重试, bab问题
分配缓冲
TLAB,Thread local allocation Buffer,TLAB, 本地线程的分配缓冲,提高分配效率,如果容量不够了,就重新重Eden区域申请。
内存空间初始化
就是给 没有初值的成员变量,进行初始值设定
设置
接下来,虚拟机堆对象进行必要的设置,例如这个对象是那个类的实例、如何找到类的元数据信息,对象的hash码,对象的GC分带年龄等信息。这些信息存放在对象的对象头之中。
对象的初始化
在上面工作完成后,从虚拟机的角度来看,一个新的对象已经产生了,从程序的角度来讲,才刚刚开始。在程序员new了之后,对象就产生了。
对象的内存布局
在hotSpot的虚拟机中,对象在内存中存储的布局分为三块区域:对象头,实例数据和对齐填充。
对象头包括两部分形象,第一部分用于存储对象自生
栈上分配
字符串存放在什么位置
基本数据类型存放在什么位置
对象的内存模型
学习垃圾回收的意义
java与C++等语言的最大技术的区别:自动化的垃圾回收机制
为什么要了解GC和内存分配策略
1、面试需要
2、GC对应的
3、写代码有好处
栈:堆中的生命周期是跟随线程,所以一般不需要关注
堆:堆中的对象是垃圾回收的重点
GC案例
自动回收机制也有失败的时候oom
新生代配置
新生代大小配置参数的优先级:
判断对象的存活
引用计数法:快,方便,实现简单,缺点:对象相互引用的时候不好判断
虚拟机栈(栈帧中常用的引用变量表)中引用对象。
方法区中类静态属性引用的对象。
方法区中常量引用的对象。
本地方法栈中JNI引用的对象
各种引用
强引用:new出来的对象都是强引用
软引用:softWeakReference 软引用即将发生oom的时候进行回收
弱引用:weakReference 发生GC的时候就会被回收,不管内存足不足,都会被回收
虚引用:垃圾回收的时候会通知一下
草稿:
异常处理器表
Class.forName() 和 ClassLoader加载类的区别
Class.forName():本质是通过ClassLoader加载的,但是会进行一些初始化操作,静态代码块的操作。
ClassLoader:只是把类记载到虚拟机中,不会有任何初始化操作
final关键在内存中的常量区,但是和static不同的是,static类进行加载后,就会被初始化,而final的是在用的时候初始化
native堆还是在用户空间,是存在数据从内核到堆外空间的拷贝的
native堆是在用户空间
堆外内存 1次拷贝
堆内存 2次拷贝
空间担保
优化一下简历