一、JVM
-----------------------------------------------------
java virtual machine
二、JAVA Runtime data area
------------------------------------------------------
1.Method area:方法区,存放Class(类描述符),Class只需要加载一次(用到谁加载谁),溢出,扩容,线程共享
2.Heap:堆区,存放对象和数组的地方,所有线程间共享
3.Java Stack:一个线程对应一个栈,每调用一个方法,就会压入一个方法帧。方法执行完毕,弹方法帧,弹栈。栈溢出错误。
4.native Method area:存放本地方法
5.program counter register:
三、JVM的内存结构
-------------------------------------------------------
1.堆区heap
-- young新生代:
-- eden区:伊甸区,对象产生的地方
-- s0:幸存一区,回收对象存放的地方
-- s1:幸存二区,回收对象存放的地方
-- old 老年代
2.非堆区non-heap
-- method area:方法区
-- metaspace:元数据空间
-- perment:持久化存储区
四、off-heap 离堆,jvm之外的内存
--------------------------------------------------------
1.unsafe:不安全,不主动回收
五、可视化界面工具:JVisualVM 和 JConsole
--------------------------------------------------------
六、jmap
-------------------------------------------------------
1.查看堆的使用信息: jmap -heap pid
2.查看永久区信息: jmap -permstat pid
3.查看类加载信息: jmap -clstats pid
七、JVM调优
--------------------------------------------------------
1.-Xms //设定堆初始值 1/64(物理内存的1/64 <1G ) -Xms150m
2.-Xmx //设定堆最大值 1/4 (物理内存的1/4 <1G) -Xmx150m
3.-Xmn //设定年轻代大小 -xmn150m
4.-XX:PermSize //设定永久代大小 -XX:PermSize=150m
5.-XX:MaxPermSize //设定永久代最大值 -XX:MaxPermSize=150m
八、ClassLoader 加载类的过程 Class.forName();
--------------------------------------------------------
1.转换类名到location path, 定位到class文件
2.加载class文件到方法区 mathord area
3.函数进入栈区,以帧压栈执行
4.函数执行完毕弹栈
九、反射:动态访问对象的属性和方法
--------------------------------------------------------
1.Class:类的描述符。描述类的特征(方法,字段等)
-- Person.class p.getClass();
-- 可以通过类描述符创建类的实例 clazz.newInstance();
2. x instanceof Person; //模糊判断,子类也可以
x.getClass() == Person.Class; //精准判断,子类也不可以
3.Method:方法描述符,描述方法的特征(参数,返回值等)
-- Method m = clazz.getDeclareMehtod("FuncName" , String.class , Integer.Class)
-- m.setAccessible(true); //设置可访问性,可以访问私有对象
-- m.invoke( clazz.newInstance() , "tom" , 18);
-- m.getModifiers(); //获取访问修饰符,返回值是所有修饰符的总和
-- m.getReturnType(); //获取返回值类型
4.Field:字段描述符。描述变量的
-- Field f = clazz.getDeclaredField("name");
-- f.setAccessible(true);
-- f.set(obj, "jerry");
-- Object o2 = f.get(obj);
5.getMothods() / getDeclareMethods();
-- getMothods得到所有可用的方法,包括继承下来的方法
-- getDeclareMethods 得到类中声明的方法,不包括继承的
-- Method [] ms = obj.getMothods();
-- String name = ms[0].getName();
-- Class [] cs = ms[0].getParameterTypes();
6.Constructor:构造函数描述符
/**
* 测试反射
*/
@Test
public void tsReflect()
{
Person p = new Person("111", 11);
Class clazz = p.getClass();
System.out.println(clazz.getName());
System.out.println(clazz.hashCode());
System.out.println(Person.class.hashCode());
}
/**
* 测试反射方法
* @throws Exception
*/
public static void tsReflectMethod1() throws Exception
{
System.out.println("xxx");
//动态加载类,得到类描述符
Class clazz = Class.forName("study.day730.ts01.Person");
//通过类描述符得到类的具体对象object
Object obj = clazz.newInstance();
//反射动态获取方法 setName(String name)
Method m = clazz.getDeclaredMethod("setName", String.class);
//调用方法 p.SetName("tom");
m.invoke(obj, "tom");
//
if(obj.getClass() == Person.class)
{
System.out.println(((Person) obj).getName());
}
//
Method m1 = clazz.getDeclaredMethod("getName");
//设置可访问性。当函数为私有的时候,需要添加可访问性
m1.setAccessible(true);
Object o1 = m1.invoke(obj);
System.out.println(o1);
//字段描述符
Field f = clazz.getDeclaredField("name");
f.setAccessible(true);
f.set(obj, "jerry");
Object o2 = f.get(obj);
System.out.println(o2);
System.out.println("-------------------");
//
Method [] ms = clazz.getMethods();
for(Method mm : ms)
{
String name = mm.getName();
Class [] cs = mm.getParameterTypes();
if(name.startsWith("get") && (cs == null || cs.length == 0))
{
System.out.println(name);
Object oo = mm.invoke(obj);
System.out.println(oo);
}
}
}
/**
* 测试构造描述符
* @throws Exception
*/
@Test
public void tsConstructor() throws Exception
{
Class clazz = Class.forName("study.day730.ts01.Person");
Constructor c1 = clazz.getDeclaredConstructor(String.class,int.class);
Object obj = c1.newInstance("tom",18);
}
十、通过反射,实现属性复制
------------------------------------------------------------------
/**
* 反射实现属性复制
*/
@Test
public void tsCopyFields()
{
Person p1 = new Person();
Person p2 = new Person();
p1.setAge(11);
p1.setName("Tom");
//tsCopyFields_1(p1,p2);
tsCopyFields_2(p1,p2);
System.out.println("xxx");
}
/**
* 通过字段复制(可以复制非同类对象)
* @param p1
* @param p2
*/
public void tsCopyFields_1(Person p1, Person p2)
{
try {
Class clazz = Person.class;
Field[] fs = clazz.getDeclaredFields();
for(Field f : fs)
{
f.setAccessible(true);
Object o1 = f.get(p1);
f.set(p2, o1);
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 通过方法复制,只能复制同类对象
* @param p1
* @param p2
*/
public void tsCopyFields_2(Person p1, Person p2)
{
try {
Class clazz = Person.class;
Method[] ms = clazz.getDeclaredMethods();
for(Method m : ms)
{
Object o = null;
//是get方法,参数为空,并且有配套的set方法
if(m.getName().startsWith("get") && (m.getParameterTypes() == null || m.getParameterTypes().length == 0))
{
o = m.invoke(p1);
for(Method m1 : ms)
{
//找到同名的set方法
if(m1.getName().startsWith("set") && (m1.getName().substring(3).equals(m.getName().substring(3))))
{
m1.invoke(p2,o);
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}