1. 程式人生 > >[JVM] - 繼10進制的java.lang.Object查看之後

[JVM] - 繼10進制的java.lang.Object查看之後

下載 不同的 members 放棄 數字 i+1 offer c++ 清除命令

cmd清除命令:cls

技術分享圖片

之後查閱了其它博客,發現這位大神同樣也在做JVM,並且我很希望用它的10進制轉16進制類來測試一下該解析的10進制是否對應著Object的16進制呢?

這位大神的10進制轉16進制代碼:

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;



public class Test {
    public static String txt2String(File file){
        StringBuilder result = new
StringBuilder(); try{ BufferedReader br = new BufferedReader(new FileReader(file));//構造一個BufferedReader類來讀取文件 String s = null; while((s = br.readLine())!=null){//使用readLine方法,一次讀一行 result.append(System.lineSeparator()+s); } br.close(); }
catch(Exception e){ e.printStackTrace(); } return result.toString(); } public static int hixTo(StringBuffer sb){ int sum=0; if(sb.charAt(0)>=48&&sb.charAt(0)<=57){ sum+=(sb.charAt(0)-48)*16; }else{ sum
+=((sb.charAt(0)-96)+9)*16; } if(sb.charAt(1)>=48&&sb.charAt(1)<=57){ sum+=(sb.charAt(1)-48); }else{ sum+=((sb.charAt(1)-96)+9); } return sum; } public static void main(String[] arts){ File file = new File("D:\\yff.txt"); String str=txt2String(file); StringBuffer sbBefore=new StringBuffer(str); StringBuffer sbAfter=new StringBuffer(); for(int i=0;i<sbBefore.length();i++){ if((sbBefore.charAt(i)>=48&&sbBefore.charAt(i)<=57)||(sbBefore.charAt(i)>=97&&sbBefore.charAt(i)<=122)){ //System.out.print(sbBefore.charAt(i)); sbAfter.append(sbBefore.charAt(i)); } } System.out.println(sbAfter); System.out.println(); for(int i=0;i<sbAfter.length();i=i+2){ System.out.print(hixTo(new StringBuffer(""+sbAfter.charAt(i)+sbAfter.charAt(i+1)))+" "); if(i!=0&&i%100==0) System.out.println(); } } }

這樣精湛的代碼著實讓人敬佩,我翻看了下之前我寫的一些類似算法的解析:

import java.util.ArrayList;
public class Fracts {


    public static String convertFrac(long[][] lst) {
        long bigFrac = 1;
        long result = 1;
//        int count = 0;//計算是否還可以
        int fracNum = 0;//原始分母數量
        int maxDLen = 0;
        ArrayList<long[]> divisor = new ArrayList();
        ArrayList<Long> members = new ArrayList<Long>();
        ArrayList<Long> fracs = new ArrayList<Long>();
        // lst是個long型的二維數組,裏面的每組元素是分子和分母的組合形式
        // 獲取其分母的公共分母,(分子也按需更改),返回三組數據的字符串形式
        for (int i = 0; i < lst.length; i++) {
            for (int j = 0; j < 2; j++) {
                if(j==1) { //開始獲取分母
                    //從上面if 開始進來了 所有的分母  多個數的最小公倍數求法:
                    //是素數的保持素數,不是素數的分解
                    long[] fracArray = new long[1];
                    long[] fracArray2 = new long[1];
                    int q;
                    int lastIndex = 0;
                    //分解質因數
                    long frac = lst[i][j];//獲取了每個二維數組的元素
                    fracs.add(frac);
                    int count = 0; //[計數]看看這個數有共幾個質因數
                    for(q=2;q<frac;q++) {
                        
                        if(frac%q==0) {
                            //如果一個數能分解,就必定還有另一個因數,所以數組大小必須大於長度1
//                            System.out.println("q:"+q);
                            //得到了這個質因數的值(多個,需要數組存放)
                            //如果對每個數值的質因數,生成不同的數組或集合存放呢?
                            count++;//有一個因數分解時,count就遞增
                            
//                            System.out.println(""+fracArray.length+":"+count);
                            if(fracArray.length<=count) {
                                fracArray = new long[count+1];//變更數組大小
                                lastIndex=count;
                                for(int h=0;h<fracArray2.length;h++) {
                                    fracArray[h] = fracArray2[h];
                                }
                            }
                            
              
                            fracArray[count-1] = q; //將質因數添加到數組
//                            System.out.println("q:"+q);
                            fracArray2 = fracArray;
                            frac = frac/q;
//                            System.out.println("frac:"+frac);
                            q=q/q;
                            
//                            
                            
                        }
                        
                    }
                    //將最後的因數裝入數組最後
          fracArray2[lastIndex] =q;
                    if(count==0) {
                        //這是個素數
                        fracArray2[0]=frac;
                    }
                    
                    divisor.add(fracArray2);
                    if(fracArray2.length>maxDLen) {
                        maxDLen = fracArray2.length;
                    }
                    
                }
                if(j==0) {
                    long mem = lst[i][j];
                    members.add(mem);
                }
            
                
            }
            

        }
        long[][] resultMatrixArr = new long[lst.length][maxDLen];
        long[][] resultMatrixArr2 = new long[maxDLen][lst.length];
        //將多個分母的分解的質因數裝入二維數組,以最長質因數數組長度為二維矩陣寬度.原lst.length為高度.
        for(int l=0;l<lst.length;l++) {
            for(int p=0;p<divisor.get(l).length;p++) {
                    resultMatrixArr[l][p]=divisor.get(l)[p];
            }
        }
        
        for(int aa=0;aa<lst.length;aa++) {//矩陣高
//            System.out.println(resultMatrixArr[aa]);
            int grow = 0;
            for(int cc=0;cc<maxDLen;cc++) {//矩陣寬
                //獲取每行的unique的集合,去除每行存在的重復數字,保留唯一一個.
                long[] rowNum = resultMatrixArr[aa]; //0,0; 0,1; 0,2
                grow=cc;
                while((grow+1)<rowNum.length) {//如果cc+1不是最大數組下標 則+1
                    grow++;
                    if(rowNum[cc]==rowNum[grow]) {
                        resultMatrixArr[aa][grow]=0;
                    }
                }
                //將二維數組倒置裝入另一個  
                resultMatrixArr2[cc][aa] = resultMatrixArr[aa][cc];    
            }
        }
        
        //豎向去除 ?? 不適用此題
//        for(int tt=0;tt<maxDLen;tt++) {//矩陣高
//            int grow = 0;
//            for(int gg=0;gg<lst.length;gg++) {
//                //獲取每列的unique集合,去除每列存在的重復數字,保留唯一一個.
//                grow=gg;
//                long[] rowNum = resultMatrixArr2[tt]; //0,0; 0,1; 0,2
//                while((grow+1)<rowNum.length) {//如果cc+1不是最大數組下標 則+1
//                    grow++;
//                    if(rowNum[gg]==rowNum[grow]) {
//                        resultMatrixArr2[tt][grow]=0;
//                    }
//                }
//            }
//        }
        for(int tt=0;tt<resultMatrixArr2.length;tt++) {//矩陣高
            for(int gg=0;gg<lst.length;gg++) {
                if(resultMatrixArr2[tt][gg]!=0) {
//                    System.out.println(resultMatrixArr2[tt][gg]);
                    result *= resultMatrixArr2[tt][gg];
                }
            }
            
        }
        
        String strResult = "";
        //獲取分母的最小公倍數後
        for(int kk=0;kk<fracs.size();kk++) {
            if (result<fracs.get(kk)) {
                result=fracs.get(kk);
            }
        }
        for(int kk=0;kk<fracs.size();kk++) {
        
            strResult += "("+result/fracs.get(kk)*members.get(kk)+","+result+")";
        }
        return strResult;
    }

}

這是在codewars做的一組題其中的一道

現在看起來還有印象的就是將首位的數組進行置換,還是怎樣,現在看到它有點暈.

技術分享圖片

當時解題的思路圖↑

當時學2進制還做了一個demo

技術分享圖片

不說啦,都是過去的事情.

只要不放棄,還是有offer的.

在查看完畢ch02後,要進入作者的ch03教程了.

首先根據那位大神的代碼讓我們看看查看的Object類的編碼是不是跟原始Object的class內容一致.

技術分享圖片

看到已經將我們通過Go語言獲取的Object類的10進制編碼轉換為了16進制.

並且開頭是cafebabe000...34...

對比原始的Object.class文件:

cafe babe 0000 0034 004e 0300 0f42 3f08
0010 0800 2608 002a 0100 0328 2949 0100
1428 294c 6a61 7661 2f6c 616e 672f 4f62
6a65 6374 3b01 0014 2829 4c6a 6176 612f
6c61 6e67 2f53 7472 696e 673b 0100 0328
2956 0100 1528 4929 4c6a 6176 612f 6c61
6e67 2f53 7472 696e 673b 0100 0428 4a29
5601 0005 284a 4929 5601 0015 284c 6a61
...

嗯,同樣是cafebabe開頭,後面000後有34,,,以及3f08,結尾是02004d,沒錯了.

以cafebabe開頭...

cafe babe
咖啡館寶貝

轉入正題:

那麽繼續查看ch03.

第三章:解析class文件

前面幾章介紹了Java虛擬機從哪裏搜索class文件,並且實現了類路徑功能,已經可以把class文件讀取到內存中.

這一章將討論class文件格式,編寫代碼解析class文件.為下一步真正實現Java虛擬機做準備.

以02為藍本復制到ch03文件夾,創建classfile子目錄.

作為類(或者接口)信息的載體,每個class文件都完整地定義了一個類,為了使Java程序可以"編寫一次,處處運行",Java虛擬機規範對class文件格式進行了嚴格的規定.

但是,對於從哪裏加載class文件,給了足夠多的自由.

Java虛擬機實現可以從文件系統讀取和從JAR(或ZIP)壓縮包中提取class文件. 以外,還可以通過網絡下載,從數據庫加載,甚至是在運行中直接生成class文件.

Java虛擬機規範中所指class文件,並非特指位於磁盤中的.class文件,而是泛指任何格式復合規範的class數據.

構成class文件的基本數據單位是字節,可以把整個class文件當成一個字節流來處理.稍大一些的數據由連續多個字節構成,這些數據在class文件中以大端(big-endian)方式存儲.

為了描述class文件格式,Java虛擬機規範定義了u1,u2,和u4三種數據類型來表示1,2,4字節無符號整數,分別對應Go語言的uint8,uint16和uint32類型.

相同類型的多條數據一般按表(table)的形式存儲在class文件中, 表由表頭和表項(item)構成,表頭是u2或u4整數,假設表頭是n,後面就緊跟著n個表項數據.

Java虛擬機規範使用一種類似C語言的結構體語法來描述class文件格式,整個class文件被描述為一個ClassFile結構.

技術分享圖片

JDK提供了功能強大的命令行工具javap,可以用它反編譯class文件.

[JVM] - 繼10進制的java.lang.Object查看之後