操作日志中,用一个方法比较不同类前后的变化

           最近项目中加操作日志的时候,对于不同的类,如果一个一个去比较,显得麻烦,故而想到写个方法,一次比较类前后变化的值。代码如下,此方法用于遍历类中的方法和值。

public String compared(BaseModel model1,BaseModel model2) throws Exception{
StringBuffer sbf = new StringBuffer();
System.out.println("halo,日志");
 Field[] field1 = model1.getClass().getDeclaredFields();        //获取实体类的所有属性,返回Field数组  
 Field[] field2 = model2.getClass().getDeclaredFields();        //获取实体类的所有属性,返回Field数组  
       for(int j=0 ; j<field1.length ; j++){     //遍历所有属性
               String name1 = field1[j].getName();    //获取属性的名字
               String name2 = field2[j].getName();    //获取属性的名字
               System.out.println("attribute name:"+name1);     
               name1 = name1.substring(0,1).toUpperCase()+name1.substring(1); //将属性的首字符大写,方便构造get,set方法
               name2 = name2.substring(0,1).toUpperCase()+name2.substring(1); //将属性的首字符大写,方便构造get,set方法
               String type1 = field1[j].getGenericType().toString();    //获取属性的类型
               String type2 = field2[j].getGenericType().toString();    //获取属性的类型
               if(type1.equals("class java.lang.String")){   //如果type是类类型,则前面包含"class ",后面跟类名
                   Method m1 = model1.getClass().getMethod("get"+name1);
                   Method m2 = model1.getClass().getMethod("get"+name2);
                   String value1 = (String) m1.invoke(model1);    //调用getter方法获取属性值
                   String value2 = (String) m1.invoke(model1);    //调用getter方法获取属性值
                   if(!value1.equals(value2)){
                            sbf.append(name1+"由"+value1+"变为:"+value2);
                       
                   }
               }
               if(type1.equals("class java.lang.Integer")){     
                   Method m1 = model1.getClass().getMethod("get"+name1);
                   Method m2 = model1.getClass().getMethod("get"+name2);
                   Integer value1 = (Integer) m1.invoke(model1);
                   Integer value2 = (Integer) m2.invoke(model2);
                   if(value1!=value2){
                    sbf.append(name1+"由"+value1+"变为:"+value2);
                   }
               }
               if(type1.equals("class java.lang.Short")){     
                   Method m1 = model1.getClass().getMethod("get"+name1);
                   Method m2 = model2.getClass().getMethod("get"+name2);
                   Short value1 = (Short) m1.invoke(model1);
                   Short value2 = (Short) m2.invoke(model2);
                   if(value1 != value2){
                    sbf.append(name1+"由"+value1+"变为:"+value2);                   }
               }       
               if(type1.equals("class java.lang.Double")){     
                   Method m1 = model1.getClass().getMethod("get"+name1);
                   Method m2 = model2.getClass().getMethod("get"+name2);
                   Double value1 = (Double) m1.invoke(model1);
                   Double value2 = (Double) m2.invoke(model2);
                   if(value1 != value2){                    
                    sbf.append(name1+"由"+value1+"变为:"+value2);
                   }
               }                  
               if(type1.equals("class java.lang.Boolean")){
                   Method m1 = model1.getClass().getMethod("get"+name1);  
                   Method m2 = model1.getClass().getMethod("get"+name2);
                   Boolean value1 = (Boolean) m1.invoke(model1);
                   Boolean value2 = (Boolean) m2.invoke(model2);
                   if(value1 != value2){                      
                    sbf.append(name1+"由"+value1+"变为:"+value2);
                   }
               }
               if(type1.equals("class java.util.Date")){
                   Method m1 = model1.getClass().getMethod("get"+name1);
                   Method m2 = model2.getClass().getMethod("get"+name2);   
                   Date value1 = (Date) m1.invoke(model1);
                   Date value2 = (Date) m2.invoke(model2);
                   if(value1 != value2){
                    sbf.append(name1+"由"+value1+"变为:"+value2);
                   }
               }   
               System.out.println("操作日志:"+sbf.toString());
           }
       
return sbf.toString();
}

<think>好的,用户想了解如何查看Java中某个方法区的内存占用情况。首先,我需要回忆方法区在JVM中的位置和作用。方法区主要用于存储的元数据,如结构、常量、静态变量等。在Java 8之前,方法区通常与永久代(PermGen)关联,但之后被元空间(Metaspace)取代。 接下来,用户的问题是如何查看指定方法区的内存占用。通常,直接查看单个方法区占用可能比较复杂,因为JVM没有提供直接的工具。不过,可以考虑使用一些JVM工具和参数来间接获取相关信息。 首先,想到的是使用JVM参数来监控元空间的使用情况。例如,设置-XX:NativeMemoryTracking=summary可以启用内存跟踪,然后通过jcmd命令来查看内存详情。此外,Metaspace的大小可以通过-XX:MaxMetaspaceSize和-XX:MetaspaceSize进行调整,但用户需要的是查看现有的占用情况。 其次,可以使用jstat工具,具体是jstat -gc <pid>,其中会显示元空间的使用量。不过这可能只能看到整体的使用情况,无法具体到某个。 然后,考虑使用Java Mission Control(JMC)或VisualVM这样的图形化工具,它们提供了更直观的内存监控界面,但同样可能无法细分到单个。 另外,用户提到引用中的方案一,通过Runtime.freeMemory()来估算内存占用差异。这种方法虽然不精确,但或许可以用于对比加载前后的内存变化。不过,这需要确保在测量时没有其他内存操作干扰,可能不太可靠。 还有,可能需要使用到Instrumentation接口,通过Java Agent来获取对象的内存大小,但这种方法通常用于堆内存中的对象,而方法区的数据可能不在其统计范围内。 综合来看,目前没有直接的方法可以精确查看单个方法区的内存占用。可能需要结合多个工具和间接方法来估算。例如,使用JMC监控元空间的变化,或者在启动时添加详细的GC日志参数,分析日志中的元空间信息。 此外,用户可能需要了解方法区内存的组成部分,包括信息、方法信息、常量池等,这些可能分散在元空间中,难以单独统计某个的占用。因此,最终的解决方案可能需要依赖JVM提供的工具进行整体分析,并结合代码实践来估算。</think>要查看Java中指定方法区的内存占用情况,可以通过以下步骤实现: ### 一、方法区内存结构说明 方法区在Java 8后由元空间(Metaspace)实现,存储的元数据名、方法、字段等)、常量池、静态变量等[^4]。 ### 二、查看方法区内存占用的方法 #### 1. 使用JVM参数监控元空间 启动时添加参数: ```shell java -XX:NativeMemoryTracking=summary -XX:+UnlockDiagnosticVMOptions -XX:+PrintNMTStatistics ``` 通过`jcmd`查看内存分配: ```shell jcmd <pid> VM.native_memory summary | grep Metaspace ``` 可获取元空间总内存占用,但无法细分到单个[^2]。 #### 2. 使用Java Mission Control (JMC) 1. 启动应用时添加JMX参数: ```shell java -Dcom.sun.management.jmxremote -XX:+UseSerialGC -XX:MetaspaceSize=64M ``` 2. 通过JMC的「内存」面板查看`Metaspace`分区的内存使用趋势。 #### 3. 通过GC日志分析 添加GC日志参数: ```shell java -Xlog:gc*,metaspace*=trace:file=gc.log ``` 在日志中搜索`Metaspace`关键词,观察元空间容量变化: ``` [metaspace ] GC(5) Metaspace: 12345K->12345K(45678K) ``` ### 三、间接估算数据占用 通过对比加载前后的内存差异: ```java long before = ManagementFactory.getMemoryMXBean().getNonHeapMemoryUsage().getUsed(); Class<?> clazz = Class.forName("com.example.MyClass"); long after = ManagementFactory.getMemoryMXBean().getNonHeapMemoryUsage().getUsed(); System.out.println("Estimated memory: " + (after - before) + " bytes"); ``` 该方法精度较低,需多次测量取平均值[^3]。 ### 四、专业工具分析 使用JVM TI接口或第三方工具: - Eclipse Memory Analyzer (MAT) 的ClassLoader分析 - JProfiler的Metaspace监控模块 可定位具体加载器的元空间占用,但需商业授权。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值