❶ 線程特有數據(Thread Specific Data)
在單線程程序中,我們經常要使用 全局變數 來實現多個函數間共享數據。在多線程環境下,由於數據空間是共享的,因此全局變數也為所有線程所共有。但有時在應用程序設計中有必要提供 線程私有 的全局變數,僅在某個線程中有效,但可以跨多個函數訪問,這樣每個線程訪問它自己獨立的數據空間,而不用擔心和其它線程的同步訪問。
這樣在一個線程內部的各個函數都能訪問、但其它線程不能訪問的變數,我們就需要使用 線程局部靜態變數 (Static memory local to a thread) 同時也可稱之為 線程特有數據 (Thread-Specific Data 或 TSD),或者 線程局部存儲 (Thread-Local Storage 或 TLS)。
POSIX 線程庫提供了如下 API 來管理線程特有數據(TSD):
第一參數 key 指向 pthread_key_t 的對象的指針。請 注意 這里 pthread_key_t 的對象佔用的空間是用戶事先分配好的, pthread_key_create 不會動態生成 pthread_key_t 對象。
第二參數 desctructor ,如果這個參數不為空,那麼當每個線程結束時,系統將調用這個函數來釋放綁定在這個鍵上的內存塊。
有時我們在線程里初始化時,需要避免重復初始化。我們希望一個線程里只調用 pthread_key_create 一次,這時就要使用 pthread_once 與它配合。
第一個參數 once_control 指向一個 pthread_once_t 對象,這個對象必須是常量 PTHREAD_ONCE_INIT ,否則 pthread_once 函數會出現不可預料的結果。
第二個參數 init_routine ,是調用的初始化函數,不能有參數,不能有返回值。
如果成功則返回0,失敗返回非0值。
創建完鍵後,必須將其與線程數據關聯起來。關聯後也可以獲得某一鍵對應的線程數據。關聯鍵和數據使用的函數為:
第一參數 key 指向鍵。
第二參數 value 是欲關聯的數據。
函數成功則返回0,失敗返回非0值。
注意: 用 pthread_setspecific 為一個鍵指定新的線程數據時,並不會主動調用析構函數釋放之前的內存,所以調用線程必須自己釋放原有的線程數據以回收內存。
獲取與某一個鍵關聯的數據使用函數的函數為:
參數 key 指向鍵。
如果有與此鍵對應的數據,則函數返回該數據,否則返回NULL。
刪除一個鍵使用的函數為:
參數 key 為要刪除的鍵。
成功則返回0,失敗返回非0值。
注意: 該函數將鍵設置為可用,以供下一次調用 pthread_key_create() 使用。它並不檢查當前是否有線程正在使用該鍵對應的線程數據,所以它並不會觸發函數 pthread_key_create 中定義的 destructor 函數,也就不會釋放該鍵關聯的線程數據所佔用的內存資源,而且在將 key 設置為可用後,在線程退出時也不會再調用析構函數。所以在將 key 設置為可用之前,必須要確定:
在 linux 中每個進程有一個全局的數組 __pthread_keys ,數組中存放著 稱為 key 的結構體,定義類似如下:
在 key 結構中 seq 為一個序列號,用來作為使用標志指示這個結構在數組中是否正在使用,初始化時被設為0,即表示 不在使用 。 destructor 用來存放一個析構函數指針。
pthread_create_key 會從數組中找到一個還未使用的 key 元素,將其序列號 seq 加1,並記錄析構函數地址,並將 key 在數組 __pthread_keys 中的 下標 作為返回值返回。那麼如何判斷一個 key 正在使用呢?
如果 key 的序列號 seq 為偶數則表示未分配,分配時將 seq 加1變成奇數,即表示正在使用。這個操作過程採用原子 CAS 來完成,以保證線程安全。在 pthread_key_delete() 時也將序列號 seq 加1,表示可以再被使用,通過序列號機制來保證回收的 key 不會被復用(復用 key 可能會導致線程在退出時可能會調用錯誤的析構函數)。但是一直加1會導致序列號回繞,還是會復用 key ,所以調用 pthread_create_key 獲取可用的 key 時會檢查是否有回繞風險,如果有則創建失敗。
除了進程范圍內的 key 結構數組外,系統還在進程中維護關於每個線程的控制塊 TCB(用於管理寄存器,線程棧等),裡面有一個 pthread_key_data 類型的數組。這個數組中的元素數量和進程中的 key 數組數量相等。 pthread_key_data 的定義類似如下:
根據 pthread_key_create() 返回的可用的 key 在 __pthread_keys 數組中的下標, pthread_setspecific() 在 pthread_key_data 的數組 中定位相同下標的一個元素 pthread_key_data ,並設置其序號 seq 設置為對應的 key 的序列號,數據指針 data 指向設置線程特有數據(TSD)的值。
pthread_getspecific() 用於將 pthread_setspecific() 設置的 data 取出。
線程退出時, pthread_key_data 中的序號 seq 用於判斷該 key 是否仍在使用中(即與在 __pthread_keys 中的同一個下標對應的 key 的序列號 seq 是否相同),若是則將 pthread_key_data 中 data(即 線程特有數據 TSD)作為參數調用析構函數。
由於系統在每個進程中 pthread_key_t 類型的數量是有限的,所有在進程中並不能獲取無限個 pthread_key_t 類型。Linux 中可以通過 PTHREAD_KEY_MAX(定義於 limits.h 文件中)或者系統調用 sysconf(_SC_THREAD_KEYS_MAX) 來確定當前系統最多支持多少個 key 。 Linux 中默認是 1024 個 key,這對大多數程序來書已經夠了。如果一個線程中有多個線程局部存儲變數(TLS),通常可以將這些變數封裝到一個數據結構中,然後使用封裝後的數據結構和一個線程局部變數相關聯,這樣就能減少對鍵值的使用。
https://blog.csdn.net/hustraiet/article/details/9857919
https://blog.csdn.net/hustraiet/article/details/9857919
https://blog.csdn.net/caigen1988/article/details/7901248
http://www.bitools.com/?p=2443
https://spockwangs.github.io/blog/2017/12/01/thread-local-storage/
https://www.jianshu.com/p/71c2f80d7bd1
https://blog.csdn.net/cywosp/article/details/26469435
http://www.embeddedlinux.org.cn/emblinuxappdev/117.htm
❷ linux建立TCP伺服器後,TCP客戶端與伺服器連接成功後,怎樣獲取客戶端的MAC地址
我認為你是從 socket中取不到這部分的信息的.
你得再操作 arp的緩存部分回才行. ARP那部分如果在特殊答情況,很亂套.比如有攻擊或是IP地址設置有沖突啥地.
---
詳細的C語言怎麼操作ARP緩存我不太清楚. 但你如果想知道.就得查一下這部分怎麼做了.
高層的socket操作是得不到的.
只有直連網段的計算機有MAC地址信息.經過路由來的數據包.取不到.
❸ linux宕機後根據地址來查看哪個函數出錯
|1)從System.map文件中直接得到地址:
$ grep sys_open /usr/src/linux/System.map
2)使用 nm 命令:
$ nm vmlinuz | grep sys_open
3)從 /proc/kallsyms 文件獲得地址:
$ cat /proc/kallsyms | grep sys_open
4)使用 kallsyms_lookup_name() 函數:版
是在kernel/kallsyms.c文件中定義的權,要使用它必須啟用CONFIG_KALLSYMS編譯內核。
kallsyms_lookup_name()接受一個字元串格式內核函數名,返回那個內核函數的地址。
kallsyms_lookup_name("sys_open");
❹ C語言 Linux 獲取調用者函數名稱
可以做到的,參考一下backtrace_symbols的實現以及相關原理,這裡面比較復雜,也比較底層,一兩句話說不清楚
你要是想通過_FUNCTION_這種方式來搞的話,可以通過如下方式:
#define m_fun(args) fun(__FILE__,__LINE__, args)
進行相應的替換即可
❺ 怎麼用C語言獲取Linux系統的網卡IP地址
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<net/if.h>
#include<netdb.h>
#include<arpa/inet.h>
#include<sys/ioctl.h>
//獲取地址
//返回IP地址字元串
intgetlocalip(char*outip)
{
inti=0;
intsockfd;
structifconfifconf;
charbuf=(char)malloc(512);
structifreq*ifreq;
char*ip;
//初始化ifconf
ifconf.ifc_len=512;
ifconf.ifc_buf=buf;
if((sockfd=socket(AF_INET,SOCK_DGRAM,0))<0)
{
return-1;
}
ioctl(sockfd,SIOCGIFCONF,&ifconf);//獲取所有介面信息
close(sockfd);
//接下來一個一個的獲取IP地址
ifreq=(structifreq*)buf;
i=ifconf.ifc_len/sizeof(structifreq);
char*pos=outip;
intcount;
for(count=0;(count<5&&i>0);i--)
{
ip=inet_ntoa(((structsockaddr_in*)&(ifreq->ifr_addr))->sin_addr);
if(strncmp(ip,"127.0.0.1",3)==0)//排除127.x.x.x,繼續下一個
{
ifreq++;
continue;
}else
{
printf("%s ",ip);
strcpy(pos,ip);
intlen=strlen(ip);
pos=' ';
pos+=len+1;
count++;
ifreq++;
}
}
free(buf);
return0;
}
//——————————-函數的調用方式————————————-
intmain(intargc,char**argv)
{
charip={'*'};
if(getlocalip(ip)==0)
{
printf("本機IP地址是:%s ",ip);
}
else
{
printf("無法獲取本機IP地址");
}
return0;
}
❻ 獲取Linux IP地址的六種方法總結
本文總結六種查看Linux IP地址的方法,方便以後的運維開發工作。
在介紹前先學習一下三個命令行篩選的主要的指令,也是頻繁使用到的命令。
1、head。 head 命令可用於查看文件的開頭部分的內容,有一個常用的參數 -n 用於顯示行數,默認為 10。
運行head --help查看說明信息:
-q 隱藏文件名
-v 顯示文件名
-c<數目> 顯示的位元組數。
-n<行數> 顯示的行數。
2、grep。 grep 命令用於查找文件里符合條件的字元串。運行grep --help查看說明信息,參數太多主要有以下幾種:
grep -r遞歸選擇。
grep -v反選,顯示不包含匹配文本的所有行。
grep -n顯示符合樣式的那一行之前。
grep -A顯示符合範本樣式的那一列之外,並顯示該行之後的內容。
3、awk。 強大的文本分析工具,命令使用過於復雜(awk --help),只需要知道 awk '{print$2}'為列印第二行數據。
4、tail 。tail命令可用於查看文件的結束部分的內容,有一個常用的參數 -n 用於顯示行數,默認為 10。tail --help查看主要的參數:
tail -n顯示最後多少行
tail -c顯示最後十個字元
tail -f 循環讀取,跟蹤顯示最後十行
5、cut。 顯示每行從開頭算起的文字。
cut -b :以位元組為單位進行分割。
cut -c :以字元為單位進行分割
cut -d :自定義分隔符,默認為製表符
cut -f :與-d一起使用,指定顯示哪個區域
無線網卡地址:
echo wlan0=`ifconfig wlan0 | head -n2 | grep inet | awk '{print$2}'`
有線網卡地址:
echo eth0=`ifconfig eth0 | head -n2 | grep inet | awk '{print$2}'`
或者命令:
ifconfig | grep "inet " | cut -d: -f2 | awk '{print $1}' | grep -v "^127."
無線網卡地址:
ip address | grep wlan0 | awk '{print$2}'
有線網卡地址:
ip address | grep eth0 | awk '{print$2}'
或者
echo eth0=`ip address show eth0 | head -n4 | grep inet | awk '{print$2}'
echo wlan0=`ip address show wlan0 | head -n4 | grep inet | awk '{print$2}'
運行hostname -help命令查看說明信息:
Program options:
-a, --alias alias names
-A, --all-fqdns all long host names (FQDNs)
-b, --boot set default hostname if none available
-d, --domain DNS domain name
-f, --fqdn, --long long host name (FQDN)
-F, --file read host name or NIS domain name from given file
-i, --ip-address addresses for the host name
-I, --all-ip-addresses all addresses for the host
-s, --short short host name
-y, --yp, --nis NIS/YP domain name
hostname -i得到環回地址127.0.1.1, hostname -I得到具體的網卡信息192.168.31.82 。
php語言查看ip就是使用函數shell_exec來執行shell命令。
比如:
<?php
echo shell_exec("echo wlan0=`ifconfig wlan0 | head -n2 | grep inet | awk '{print$2}'`");
?>
然後執行php ip.php 。shell_exec()裡面可以放置任何shell命令。這個方法的意義在於php可以通過網頁對外提供服務。
#!/usr/bin/env python
import socket
import fcntl
import struct
def get_ip_address(ifname):
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
return socket.inet_ntoa(fcntl.ioctl(
s.fileno(),
0x8915, # SIOCGIFADDR
struct.pack('256s', ifname[:15])
)[20:24])
Local_wlan0=get_ip_address("wlan0")
Local_lo=get_ip_address("lo")
#Local_eth0=get_ip_address("eth0")
print Local_wlan0
print Local_lo
#print Local_eth0
利用socket包,然後執行python ip.py 得到wlan0信息。
#!/usr/bin/env python
import os
def get_ip():
out = os.popen("echo wlan0=`ifconfig wlan0 | head -n2 | grep inet | awk '{print$2}'`").read()
print out
if __name__ == '__main__':
get_ip()
和php的shell_exec函數類似,os.popen()裡面可以放置任何shell命令。注意有個函數os.system的結果只是命令執行結果的返回值,執行成功為0;os.popen()可以讀出執行的內容,輸出的結果比較特殊,帶換行符\n 。
❼ Linux下怎樣在進程中獲取虛擬地址對應的物理地址
Linux文件目錄中的/proc記錄著當前進程的信息,稱其為虛擬文件系統。在/proc下有一個鏈接目錄名為self,這意味著哪一個進程打開了它,self中存儲的信息就是所鏈接進程的。self中有一個名為page_map的文件,專門用來記錄所鏈接進程的物理頁號信息。這樣通過/proc/pid/page_map文件,允許一個用戶態的進程查看到每個虛擬頁映射到的物理頁
/proc/pid/page_map中的每一項都包含了一個64位的值,這個值內容如下所示。每一項的映射方式不同於真正的虛擬地址映射,其文件中遵循獨立的對應關系,即虛擬地址相對於0x0經過的頁面數是對應項在文件中的偏移量
* /proc/pid/pagemap. This file lets a userspace process find out which
physical frame each virtual page is mapped to. It contains one 64-bit
value for each virtual page, containing the following data (from
fs/proc/task_mmu.c, above pagemap_read):
* Bits 0-54 page frame number (PFN) if present//present為1時,bit0-54表示物理頁號
* Bits 0-4 swap type if swapped
* Bits 5-54 swap offset if swapped
* Bit 55 pte is soft-dirty (see Documentation/vm/soft-dirty.txt)
* Bit 56 page exclusively mapped (since 4.2)
* Bits 57-60 zero
* Bit 61 page is file-page or shared-anon (since 3.5)
* Bit 62 page swapped
* Bit 63 page present//如果為1,表示當前物理頁在內存中;為0,表示當前物理頁不在內存中
在計算物理地址時,只需要找到虛擬地址的對應項,再通過對應項中的bit63判斷此物理頁是否在內存中,若在內存中則對應項中的物理頁號加上偏移地址,就能得到物理地址
通過程序獲取物理地址並驗證寫時拷貝技術
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdint.h>
//計算虛擬地址對應的地址,傳入虛擬地址vaddr,通過paddr傳出物理地址
void mem_addr(unsigned long vaddr, unsigned long *paddr)
{
int pageSize = getpagesize();//調用此函數獲取系統設定的頁面大小
unsigned long v_pageIndex = vaddr / pageSize;//計算此虛擬地址相對於0x0的經過的頁面數
unsigned long v_offset = v_pageIndex * sizeof(uint64_t);//計算在/proc/pid/page_map文件中的偏移量
unsigned long page_offset = vaddr % pageSize;//計算虛擬地址在頁面中的偏移量
uint64_t item = 0;//存儲對應項的值
int fd = open("/proc/self/pagemap", O_RDONLY);。。以只讀方式打開/proc/pid/page_map
if(fd == -1)//判斷是否打開失敗
{
printf("open /proc/self/pagemap error
");
return;
}
if(lseek(fd, v_offset, SEEK_SET) == -1)//將游標移動到相應位置,即對應項的起始地址且判斷是否移動失敗
{
printf("sleek error
");
return;
}
if(read(fd, &item, sizeof(uint64_t)) != sizeof(uint64_t))//讀取對應項的值,並存入item中,且判斷讀取數據位數是否正確
{
printf("read item error
");
return;
}
if((((uint64_t)1 << 63) & item) == 0)//判斷present是否為0
{
printf("page present is 0
");
return ;
}
uint64_t phy_pageIndex = (((uint64_t)1 << 55) - 1) & item;//計算物理頁號,即取item的bit0-54
*paddr = (phy_pageIndex * pageSize) + page_offset;//再加上頁內偏移量就得到了物理地址
}
const int a = 100;//全局常量
int main()
{
int b = 100;//局部變數
static c = 100;//局部靜態變數
const int d = 100;//局部常量
char *str = "Hello World!";
unsigned long phy = 0;//物理地址
char *p = (char*)malloc(100);//動態內存
int pid = fork();//創建子進程
if(pid == 0)
{
//p[0] = '1';//子進程中修改動態內存
mem_addr((unsigned long)&a, &phy);
printf("pid = %d, virtual addr = %x , physical addr = %x
", getpid(), &a, phy);
}
else
{
mem_addr((unsigned long)&a, &phy);
printf("pid = %d, virtual addr = %x , physical addr = %x
", getpid(), &a, phy);
}
sleep(100);
free(p);
waitpid();
return 0;
}
測試結果如下:
全局常量:符合寫時拷貝技術
子進程修改動態內存
*其實想要知道虛擬地址對應的物理地址,通過這樣的方式也可以得到物理地址而不用操作MMU。。。*
以上就是Linux下怎樣在進程中獲取虛擬地址對應的物理地址的全文介紹,希望對您學習和使用linux系統開發有所幫助.
❽ 為什麼顯示不出析構函數
分類: 電腦/網路 >> 程序設計 >> 其他編程語言
問題描述:
程序正確.照抄書上例題.但是結果卻有點不同.顯示不出析構函數.例題中注釋的那行.應該要在結果中輸出..可是其它都對,就是不輸出..不知道為什麼?
#include<iostream>
#include<string>
using namespace std;
class Student
{public:
Student(int a1,string a2)
{cout<<"構造函數!"<<a1<<endl;num=a1;nam=a2;}
~Student() {cout<<"析構函數!"<<num<<endl;}/**********此為析構函數要輸出**************/
void print();
private:
int num;string nam;
}s1(101,"劉德華"),s2(0,"張學友");
void Student::print()
{if(num==0) throw num;
else cout<<num<<" "<<nam<<endl;}
void A()
{s1.print();s2.print();}
int main()
{try {A();}
catch(int a1) {cout<<"num="<<a1<<",錯誤!"<<endl;}
return 0;}
解析:
如果你要使用C++標准庫(iostream中的cout即C++標准庫的東東),請不要使用低版本的編譯器,例如在VC6中,這段程序就不能正確執行,即不能輸出析構函數里的語句。
使用VC7(里的)就可以正確執行,使用LINUX和UNIX的GCC也沒問題。
當然你也可修改析構函數里的cout<<"析構函數!"<<num<<endl;這句話為:
printf("析構函數!%d\n", num);
這樣在VC6中就可以輸出,因為printf不是C++標准庫的,而是C標准庫的。
❾ linux系統函數怎麼獲取ip地址
ifconfig命令獲取網卡地址,再過濾一下ip就出來了
ifconfig | grep '[0-9]\{1,3\}\.[0-9]\{1,3\}\.'|cut -d ":" -f2| cut -d " " -f1 | sed -n "1p"
❿ 有誰知道linux系統環境下,怎樣在後台才能獲取到mac地址
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
/**
* 與系統相關的一些常用工具方法.
*
* @author stephen
* @version 1.0.0
*/
public class SystemTool {
/**
* 獲取當前操作系統名稱.
* return 操作系統名稱 例如:windows xp,linux 等.
*/
public static String getOSName() {
return System.getProperty("os.name").toLowerCase();
}
/**
* 獲取unix網卡的mac地址.
* 非windows的系統默認調用本方法獲取.如果有特殊系統請繼續擴充新的取mac地址方法.
* @return mac地址
*/
public static String getUnixMACAddress() {
String mac = null;
BufferedReader bufferedReader = null;
Process process = null;
try {
process = Runtime.getRuntime().exec("ifconfig eth0");// linux下的命令,一般取eth0作為本地主網卡 顯示信息中包含有mac地址信息
bufferedReader = new BufferedReader(new InputStreamReader(process
.getInputStream()));
String line = null;
int index = -1;
while ((line = bufferedReader.readLine()) != null) {
index = line.toLowerCase().indexOf("hwaddr");// 尋找標示字元串[hwaddr]
if (index >= 0) {// 找到了
mac = line.substring(index +"hwaddr".length()+ 1).trim();// 取出mac地址並去除2邊空格
break;
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (bufferedReader != null) {
bufferedReader.close();
}
} catch (IOException e1) {
e1.printStackTrace();
}
bufferedReader = null;
process = null;
}
return mac;
}
/**
* 獲取widnows網卡的mac地址.
* @return mac地址
*/
public static String getWindowsMACAddress() {
String mac = null;
BufferedReader bufferedReader = null;
Process process = null;
try {
process = Runtime.getRuntime().exec("ipconfig /all");// windows下的命令,顯示信息中包含有mac地址信息
bufferedReader = new BufferedReader(new InputStreamReader(process
.getInputStream()));
String line = null;
int index = -1;
while ((line = bufferedReader.readLine()) != null) {
index = line.toLowerCase().indexOf("physical address");// 尋找標示字元串[physical address]
if (index >= 0) {// 找到了
index = line.indexOf(":");// 尋找":"的位置
if (index>=0) {
mac = line.substring(index + 1).trim();// 取出mac地址並去除2邊空格
}
break;
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (bufferedReader != null) {
bufferedReader.close();
}
} catch (IOException e1) {
e1.printStackTrace();
}
bufferedReader = null;
process = null;
}
return mac;
}
/**
* 測試用的main方法.
*
* @param argc
* 運行參數.
*/
public static void main(String[] argc) {
String os = getOSName();
System.out.println(os);
if(os.startsWith("windows")){
//本地是windows
String mac = getWindowsMACAddress();
System.out.println(mac);
}else{
//本地是非windows系統 一般就是unix
String mac = getUnixMACAddress();
System.out.println(mac);
}
}
}
-------------------------------------------------------------------------
本程序可以正確獲得本機IP地址和網卡"eth0"的MAC地址,已經在windowsXP和ubuntu-Linux上測試過
(注意:如果有多塊網卡,可能出錯)
下面給出代碼:
import java.net.*;import java.util.*;
public class Test { public static void main(String[] args) { Test t = new Test(); System.out.println(t.getLocalIP()); System.out.println(t.getMacAddr()); }
public String getMacAddr() { String MacAddr = ""; String str = ""; try { NetworkInterface NIC = NetworkInterface.getByName("eth0"); byte[] buf = NIC.getHardwareAddress(); for (int i = 0; i < buf.length; i++) { str = str + byteHEX(buf[i]); } MacAddr = str.toUpperCase(); } catch (SocketException e) { e.printStackTrace(); System.exit(-1); } return MacAddr; }
public String getLocalIP() { String ip = ""; try { Enumeration<?> e1 = (Enumeration<?>) NetworkInterface .getNetworkInterfaces(); while (e1.hasMoreElements()) { NetworkInterface ni = (NetworkInterface) e1.nextElement(); if (!ni.getName().equals("eth0")) { continue; } else { Enumeration<?> e2 = ni.getInetAddresses(); while (e2.hasMoreElements()) { InetAddress ia = (InetAddress) e2.nextElement(); if (ia instanceof Inet6Address) continue; ip = ia.getHostAddress(); } break; } } } catch (SocketException e) { e.printStackTrace(); System.exit(-1); } return ip; }
/* 一個將位元組轉化為十六進制ASSIC碼的函數 */ public static String byteHEX(byte ib) { char[] Digit = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; char[] ob = new char[2]; ob[0] = Digit[(ib >>> 4) & 0X0F]; ob[1] = Digit[ib & 0X0F]; String s = new String(ob); return s; }}