赞
踩
公司项目有个比较偏门的需求,需要在java进程里找到并修改libjvm.so里定义的一个类的static + private的成员变量,但是一直没有找到该变量的符号和地址。因此想通过c的程序来验证一下,确定是不是libjvm.so的问题,于是自己写了一个简单的demo,没想到折腾了2个小时,以此为记;
代码很简单,so的代码分为b.h和b.cpp;
b.h:
#ifndef B_H_
#define B_H_
class BClass
{
private:
static int static_private_var;
public:
int static_var;
static void set_private_var(int var_in) ;
static int get_private_var() ;
};
int b_test();
#endif
b.cpp:
#include <iostream> #include <unistd.h> #include "b.h" using namespace std; void BClass::set_private_var(int var_in) { static_private_var = var_in; } int BClass::get_private_var() { return static_private_var; } int b_test() { BClass bClassObj; bClassObj.set_private_var(5); while(1) { int cur_private_var = bClassObj.get_private_var(); cout << "cur_private_var = " << cur_private_var << endl; if(cur_private_var > 0) { cur_private_var = cur_private_var - 1; bClassObj.set_private_var(cur_private_var); sleep(10); } else { break; } } cout << "end of b_test " << endl; return 1; }
编译命令:
g++ b.cpp -o libb.so -fPIC -shared
最终生成libb.so
就一个cpp:
#include <iostream>
#include <unistd.h>
#include "b.h"
using namespace std;
int main()
{
b_test();
return 1;
}
编译命令:
g++ a.cpp -L. -lb -o a_out -I ./
ps:可能需要设置一下 LD_LIBRARY_PATH
export LD_LIBRARY_PATH=/home/admin/cus/cur:$LD_LIBRARY_PATH
链接libb.so的时候出问题了:
-bash-4.2$ g++ a.cpp -L. -lb -o a_out -I ./
./libb.so:对‘BClass::static_private_var’未定义的引用
collect2: 错误:ld 返回 1
一开始看到这个错误,感觉很奇怪,为啥会有这个错误呢?为啥在编译libb.so时不出问题,但是链接libb.so的时候才出问题?
网上查了相关资料,比如说链接的顺序、模板类的定义与实现等,都不是这个错误的原因。
没有办法,为啥会只报这个变量的错误呢?就把这个static变量改成了普通的、非static的成员变量,是可以的。
那么可以确定就是“static”的问题了,static的成员变量,与全局变量类似,可以认为是一个未经初始化的全局变量,编译时是分在bss段里,不占用文件的静态空间;那么可以理解为啥编译libb.so的时候没有问题,但是链接libb.so的时候出问题了,这是因为链接libb.so的时候是成为可执行文件了;
在b.cpp里添加该变量的初始化:
int BClass::static_private_var = 1;
还是要多读书
回头看了一下libjvm.so里的那个变量(_initialized),为何这个变量就不需要进行这样的显式的初始化呢?
class AttachListener: AllStatic { public: static void vm_start() NOT_SERVICES_RETURN; static void init() NOT_SERVICES_RETURN; static void abort() NOT_SERVICES_RETURN; // invoke to perform clean-up tasks when all clients detach static void detachall() NOT_SERVICES_RETURN; // indicates if the Attach Listener needs to be created at startup static bool init_at_startup() NOT_SERVICES_RETURN_(false); // indicates if we have a trigger to start the Attach Listener static bool is_init_trigger() NOT_SERVICES_RETURN_(false); #if !INCLUDE_SERVICES static bool is_attach_supported() { return false; } #else private: static volatile bool _initialized; public: static bool is_initialized() { return _initialized; } static void set_initialized() { _initialized = true; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。