Use lazy initialization for Java class identifiers to avoid global reference table overflow on some Android 4 devices.

This commit is contained in:
levlam 2023-04-26 17:15:53 +03:00
parent c62de5138c
commit 36a45607f2
6 changed files with 36 additions and 17 deletions

View File

@ -168,8 +168,7 @@ static jint register_native(JavaVM *vm) {
#undef TD_OBJECT #undef TD_OBJECT
td::jni::init_vars(env, PACKAGE_NAME); td::jni::init_vars(env, PACKAGE_NAME);
td::td_api::Object::init_jni_vars(env, PACKAGE_NAME); td::td_api::set_package_name(PACKAGE_NAME);
td::td_api::Function::init_jni_vars(env, PACKAGE_NAME);
return JAVA_VERSION; return JAVA_VERSION;
} }

View File

@ -129,7 +129,8 @@ class DoxygenTlDocumentationGenerator extends TlDocumentationGenerator
preg_match('/class [A-Za-z0-9_]*;/', $line) || $tline === 'if (value == nullptr) {' || preg_match('/class [A-Za-z0-9_]*;/', $line) || $tline === 'if (value == nullptr) {' ||
strpos($tline, 'result += ') === 0 || strpos($tline, 'result = ') || strpos($tline, ' : values') || strpos($tline, 'result += ') === 0 || strpos($tline, 'result = ') || strpos($tline, ' : values') ||
strpos($line, 'JNIEnv') || strpos($line, 'jfieldID') || $tline === 'virtual ~Object() {' || strpos($line, 'JNIEnv') || strpos($line, 'jfieldID') || $tline === 'virtual ~Object() {' ||
$tline === 'virtual void store(TlStorerToString &s, const char *field_name) const = 0;'; $tline === 'virtual void store(TlStorerToString &s, const char *field_name) const = 0;' ||
$tline === 'void set_package_name(const char *new_package_name);';
} }
protected function isHeaderLine($line) protected function isHeaderLine($line)

View File

@ -11,6 +11,14 @@
namespace td { namespace td {
std::string TD_TL_writer_jni_cpp::gen_output_begin() const {
return TD_TL_writer_cpp::gen_output_begin() +
"\nstatic const char *package_name = \"Call set_package_name\";\n\n"
"void set_package_name(const char *new_package_name) {\n"
" package_name = new_package_name;\n"
"}\n";
}
bool TD_TL_writer_jni_cpp::is_built_in_simple_type(const std::string &name) const { bool TD_TL_writer_jni_cpp::is_built_in_simple_type(const std::string &name) const {
return name == "Bool" || name == "Int32" || name == "Int53" || name == "Int64" || name == "Double" || return name == "Bool" || name == "Int32" || name == "Int53" || name == "Int64" || name == "Double" ||
name == "String" || name == "Bytes"; name == "String" || name == "Bytes";
@ -397,7 +405,10 @@ std::string TD_TL_writer_jni_cpp::gen_fetch_function_begin(const std::string &pa
if (field_count == 0 && vars.empty()) { if (field_count == 0 && vars.empty()) {
result += " return make_object<" + class_name + ">();\n"; result += " return make_object<" + class_name + ">();\n";
} else { } else {
result += " " + fetched_type + "res = make_object<" + class_name + ">();\n"; result +=
" init_jni_vars(env);\n"
" " +
fetched_type + "res = make_object<" + class_name + ">();\n";
} }
} }
return result; return result;
@ -462,7 +473,8 @@ std::string TD_TL_writer_jni_cpp::gen_store_function_begin(const std::string &st
"void " + "void " +
class_name + "::store(" + storer_name + " &s" + class_name + "::store(" + storer_name + " &s" +
std::string(storer_type <= 0 ? "" : ", const char *field_name") + ") const {\n" + std::string(storer_type <= 0 ? "" : ", const char *field_name") + ") const {\n" +
(storer_type <= 0 ? " s = env->AllocObject(Class);\n" (storer_type <= 0 ? " init_jni_vars(env);\n"
" s = env->AllocObject(Class);\n"
" if (!s) { return; }\n" " if (!s) { return; }\n"
: " if (!LOG_IS_STRIPPED(ERROR)) {\n" : " if (!LOG_IS_STRIPPED(ERROR)) {\n"
" s.store_class_begin(field_name, \"" + " s.store_class_begin(field_name, \"" +
@ -566,8 +578,9 @@ std::string TD_TL_writer_jni_cpp::gen_additional_function(const std::string &fun
"\n" "\n"
"void " + "void " +
class_name + "::" + function_name + class_name + "::" + function_name +
"(JNIEnv *env, const char *package_name) {\n" "(JNIEnv *env) {\n"
" " + " static bool is_inited = [&] {\n"
" " +
class_name_class + " = jni::get_jclass(env, " + gen_java_class_name(gen_class_name(t->name)) + ");\n"; class_name_class + " = jni::get_jclass(env, " + gen_java_class_name(gen_class_name(t->name)) + ");\n";
if (!t->args.empty()) { if (!t->args.empty()) {
@ -596,11 +609,14 @@ std::string TD_TL_writer_jni_cpp::gen_additional_function(const std::string &fun
} }
type_signature = new_type_signature + ").c_str()"; type_signature = new_type_signature + ").c_str()";
} }
res += " " + field_name + "fieldID = jni::get_field_id(env, " + class_name_class + ", \"" + java_field_name + res += " " + field_name + "fieldID = jni::get_field_id(env, " + class_name_class + ", \"" + java_field_name +
"\", " + type_signature + ");\n"; "\", " + type_signature + ");\n";
} }
} }
res += "}\n"; res +=
" return true;\n"
" }();\n"
"}\n";
return res; return res;
} }
@ -613,7 +629,7 @@ std::string TD_TL_writer_jni_cpp::gen_additional_proxy_function_begin(const std:
return "\n" return "\n"
"void " + "void " +
class_name + "::" + function_name + class_name + "::" + function_name +
"(JNIEnv *env, const char *package_name) {\n" "(JNIEnv *env) {\n"
" Class = jni::get_jclass(env, " + " Class = jni::get_jclass(env, " +
gen_java_class_name(class_name) + ");\n"; gen_java_class_name(class_name) + ");\n";
} }
@ -623,7 +639,7 @@ std::string TD_TL_writer_jni_cpp::gen_additional_proxy_function_case(const std::
const std::string &class_name, int arity) const { const std::string &class_name, int arity) const {
assert(function_name == "init_jni_vars"); assert(function_name == "init_jni_vars");
assert(arity == 0); assert(arity == 0);
return " " + class_name + "::" + function_name + "(env, package_name);\n"; return "";
} }
std::string TD_TL_writer_jni_cpp::gen_additional_proxy_function_case(const std::string &function_name, std::string TD_TL_writer_jni_cpp::gen_additional_proxy_function_case(const std::string &function_name,
@ -632,7 +648,7 @@ std::string TD_TL_writer_jni_cpp::gen_additional_proxy_function_case(const std::
bool is_function) const { bool is_function) const {
assert(function_name == "init_jni_vars"); assert(function_name == "init_jni_vars");
assert(arity == 0); assert(arity == 0);
return " " + gen_class_name(t->name) + "::" + function_name + "(env, package_name);\n"; return "";
} }
std::string TD_TL_writer_jni_cpp::gen_additional_proxy_function_end(const std::string &function_name, std::string TD_TL_writer_jni_cpp::gen_additional_proxy_function_end(const std::string &function_name,

View File

@ -16,14 +16,14 @@
namespace td { namespace td {
class TD_TL_writer_jni_cpp final : public TD_TL_writer_cpp { class TD_TL_writer_jni_cpp final : public TD_TL_writer_cpp {
std::string gen_output_begin() const final;
std::string gen_vector_fetch(std::string field_name, const tl::tl_tree_type *t, std::string gen_vector_fetch(std::string field_name, const tl::tl_tree_type *t,
const std::vector<tl::var_description> &vars, int parser_type) const; const std::vector<tl::var_description> &vars, int parser_type) const;
std::string gen_vector_store(const std::string &field_name, const tl::tl_tree_type *t, std::string gen_vector_store(const std::string &field_name, const tl::tl_tree_type *t,
const std::vector<tl::var_description> &vars, int storer_type) const; const std::vector<tl::var_description> &vars, int storer_type) const;
std::string package_name;
std::string gen_java_field_name(std::string name) const; std::string gen_java_field_name(std::string name) const;
std::string gen_basic_java_class_name(std::string name) const; std::string gen_basic_java_class_name(std::string name) const;

View File

@ -122,7 +122,9 @@ std::string TD_TL_writer_jni_h::gen_output_begin() const {
" }\n" " }\n"
"\n" "\n"
" return to_string(*value);\n" " return to_string(*value);\n"
"}\n\n"; "}\n\n"
"void set_package_name(const char *new_package_name);\n\n";
} }
std::string TD_TL_writer_jni_h::gen_class_begin(const std::string &class_name, const std::string &base_class_name, std::string TD_TL_writer_jni_h::gen_class_begin(const std::string &class_name, const std::string &base_class_name,
@ -157,7 +159,7 @@ std::string TD_TL_writer_jni_h::gen_additional_function(const std::string &funct
if (function_name == "init_jni_vars") { if (function_name == "init_jni_vars") {
return "\n" return "\n"
" static void " + " static void " +
function_name + "(JNIEnv *env, const char *package_name);\n"; function_name + "(JNIEnv *env);\n";
} }
return TD_TL_writer_h::gen_additional_function(function_name, t, is_function); return TD_TL_writer_h::gen_additional_function(function_name, t, is_function);
@ -170,7 +172,7 @@ std::string TD_TL_writer_jni_h::gen_additional_proxy_function_begin(const std::s
if (function_name == "init_jni_vars") { if (function_name == "init_jni_vars") {
return "\n" return "\n"
" static void " + " static void " +
function_name + "(JNIEnv *env, const char *package_name);\n"; function_name + "(JNIEnv *env);\n";
} }
return TD_TL_writer_h::gen_additional_proxy_function_begin(function_name, type, class_name, arity, is_function); return TD_TL_writer_h::gen_additional_proxy_function_begin(function_name, type, class_name, arity, is_function);

View File

@ -108,6 +108,7 @@ jobjectArray store_vector(JNIEnv *env, const std::vector<std::string> &v);
template <class T> template <class T>
jobjectArray store_vector(JNIEnv *env, const std::vector<T> &v) { jobjectArray store_vector(JNIEnv *env, const std::vector<T> &v) {
auto length = static_cast<jint>(v.size()); auto length = static_cast<jint>(v.size());
T::element_type::init_jni_vars(env);
jobjectArray arr = env->NewObjectArray(length, T::element_type::Class, jobject()); jobjectArray arr = env->NewObjectArray(length, T::element_type::Class, jobject());
if (arr != nullptr) { if (arr != nullptr) {
for (jint i = 0; i < length; i++) { for (jint i = 0; i < length; i++) {