Java复习之知识点整理(三十)--- JVM内存结构,Runtime data area,off-heap,反射

一、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();
		}	
	}


 

猜你喜欢

转载自blog.csdn.net/xcvbxv01/article/details/81286820