在上一篇文章中,小编为您详细介绍了关于《精液对女性有作用么?不带避孕套进行运动男性高潮前是否会有精液进入女性生殖器官》相关知识。本篇中小编将再为您讲解标题问一个比较小白的问题java中for循环里面new一个数组?jvm字符串的创建指令的问题。
①个很大的for里面,有①句
arr =new int[N];
arr是for外面的变量,我想给它清⓪。我想问每次都new①个变量会不会让内存开销线性增加。
还有java有没有类似c的memset
刚刚写了个代码验证了①下,内存使用量是上升的,直到(可能是GC了)某个值:
代码如下:
public class TestNewObject { public static void main(String[] args) { for (int i = ⓪; i < ①⓪⓪⓪⓪⓪⓪; i++) { String str = new String(\"test\"); if (i % ①⓪⓪⓪⓪⓪ == ⓪) { String memUsage = String.format(\"maxMemory=%d,totalMemory=%d,freeMemory=%d\", Runtime.getRuntime().maxMemory(), Runtime.getRuntime().totalMemory(), Runtime.getRuntime().freeMemory()); System.out.println(memUsage); } } }}输出如下:maxMemory=③⑥⑧⑨④①④⑥⑤⑥ · totalMemory=②④⑨⑤⑥①⓪⑧⑧ · freeMemory=②④④③①⑦⑨⑦⑥maxMemory=③⑥⑧⑨④①④⑥⑤⑥ · totalMemory=②④⑨⑤⑥①⓪⑧⑧ · freeMemory=②④⓪④⓪④⑧⑨⑥maxMemory=③⑥⑧⑨④①④⑥⑤⑥ · totalMemory=②④⑨⑤⑥①⓪⑧⑧ · freeMemory=②③⑨⓪⑨④①⑦⑥maxMemory=③⑥⑧⑨④①④⑥⑤⑥ · totalMemory=②④⑨⑤⑥①⓪⑧⑧ · freeMemory=②③⑥④⑦②⑦③⑥maxMemory=③⑥⑧⑨④①④⑥⑤⑥ · totalMemory=②④⑨⑤⑥①⓪⑧⑧ · freeMemory=②③②⑤④⓪④⑧⓪maxMemory=③⑥⑧⑨④①④⑥⑤⑥ · totalMemory=②④⑨⑤⑥①⓪⑧⑧ · freeMemory=②②⑨⑨①⑨⓪④⓪maxMemory=③⑥⑧⑨④①④⑥⑤⑥ · totalMemory=②④⑨⑤⑥①⓪⑧⑧ · freeMemory=②②⑧⑥⓪⑧③②⓪maxMemory=③⑥⑧⑨④①④⑥⑤⑥ · totalMemory=②④⑨⑤⑥①⓪⑧⑧ · freeMemory=②②⑧⑥⓪⑧③②⓪maxMemory=③⑥⑧⑨④①④⑥⑤⑥ · totalMemory=②④⑨⑤⑥①⓪⑧⑧ · freeMemory=②②⑧⑥⓪⑧③②⓪maxMemory=③⑥⑧⑨④①④⑥⑤⑥ · totalMemory=②④⑨⑤⑥①⓪⑧⑧ · freeMemory=②②⑧⑥⓪⑧③②⓪Process finished with exit code ⓪如果我们主动gc,则会更快的到达某个值:public class TestNewObject { public static void main(String[] args) { for (int i = ⓪; i < ①⓪⓪⓪⓪⓪⓪; i++) { String str = new String(\"test\"); if (i % ①⓪⓪⓪⓪⓪ == ⓪) { System.gc(); String memUsage = String.format(\"maxMemory=%d,totalMemory=%d,freeMemory=%d\", Runtime.getRuntime().maxMemory(), Runtime.getRuntime().totalMemory(), Runtime.getRuntime().freeMemory()); System.out.println(memUsage); } } }}输出如下:maxMemory=③⑥⑧⑨④①④⑥⑤⑥ · totalMemory=②④⑨⑤⑥①⓪⑧⑧ · freeMemory=②④⑥①⑧⑨⑧④⑧maxMemory=③⑥⑧⑨④①④⑥⑤⑥ · totalMemory=②④⑨⑤⑥①⓪⑧⑧ · freeMemory=②④⑦③②⑨③⑧④maxMemory=③⑥⑧⑨④①④⑥⑤⑥ · totalMemory=②④⑨⑤⑥①⓪⑧⑧ · freeMemory=②④⑦③③⓪④④⓪maxMemory=③⑥⑧⑨④①④⑥⑤⑥ · totalMemory=②④⑨⑤⑥①⓪⑧⑧ · freeMemory=②④⑦③③⓪④④⓪maxMemory=③⑥⑧⑨④①④⑥⑤⑥ · totalMemory=②④⑨⑤⑥①⓪⑧⑧ · freeMemory=②④⑦③③⓪④⓪⑧maxMemory=③⑥⑧⑨④①④⑥⑤⑥ · totalMemory=②④⑨⑤⑥①⓪⑧⑧ · freeMemory=②④⑦③③⓪④⓪⑧maxMemory=③⑥⑧⑨④①④⑥⑤⑥ · totalMemory=②④⑨⑤⑥①⓪⑧⑧ · freeMemory=②④⑦③③⓪④⓪⑧maxMemory=③⑥⑧⑨④①④⑥⑤⑥ · totalMemory=②④⑨⑤⑥①⓪⑧⑧ · freeMemory=②④⑦③③⓪④⓪⑧maxMemory=③⑥⑧⑨④①④⑥⑤⑥ · totalMemory=②④⑨⑤⑥①⓪⑧⑧ · freeMemory=②④⑦③③⓪④⓪⑧maxMemory=③⑥⑧⑨④①④⑥⑤⑥ · totalMemory=②④⑨⑤⑥①⓪⑧⑧ · freeMemory=②④⑦③③⓪④⓪⑧Process finished with exit code ⓪
泻药。根据题主的第②个问题写出①个实例代码:
public class StringTest { public static void main(String[] args) { String a = \"a\"; }}
javap -verbose 之后:
public class StringTest minor version: ⓪ major version: ⑤② flags: ACC_PUBLIC, ACC_SUPERConstant pool: #① = Methodref #④.#②⓪ // java/lang/Object.\"\":()V #② = String #①⑥ // a #③ = Class #②① // StringTest #④ = Class #②② // java/lang/Object #⑤ = Utf⑧ #⑥ = Utf⑧ ()V #⑦ = Utf⑧ Code #⑧ = Utf⑧ LineNumberTable #⑨ = Utf⑧ LocalVariableTable #①⓪ = Utf⑧ this #①① = Utf⑧ LStringTest; #①② = Utf⑧ main #①③ = Utf⑧ ([Ljava/lang/String;)V #①④ = Utf⑧ args #①⑤ = Utf⑧ [Ljava/lang/String; #①⑥ = Utf⑧ a #①⑦ = Utf⑧ Ljava/lang/String; #①⑧ = Utf⑧ SourceFile #①⑨ = Utf⑧ StringTest.java #②⓪ = NameAndType #⑤:#⑥ // \"\":()V #②① = Utf⑧ StringTest #②② = Utf⑧ java/lang/Object{ public StringTest(); descriptor: ()V flags: ACC_PUBLIC Code: stack=① · locals=① · args_size=① ⓪: aload_⓪ ①: invokespecial #① // Method java/lang/Object.\"\":()V ④: return LineNumberTable: line ④: ⓪ LocalVariableTable: Start Length Slot Name Signature ⓪ ⑤ ⓪ this LStringTest; public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: ACC_PUBLIC, ACC_STATIC Code: stack=① · locals=② · args_size=① ⓪: ldc #② // String a ②: astore_① ③: return LineNumberTable: line ⑥: ⓪ line ⑦: ③ LocalVariableTable: Start Length Slot Name Signature ⓪ ④ ⓪ args [Ljava/lang/String; ③ ① ① a Ljava/lang/String;}
可以在class文件的常量池中找到“a”的所在,我们知道当StringTest被引用时,会被类加载器加载,加载的过程中,首先要对class文件进行解析;解析的过程是按照class文件的结构来①步步地进行局部解析的,常量池解析也是这个过程中的①个步骤;在这个步骤中,字符串“a”最终作为①个Utf⑧的字面量被塞进了符号表SymbolTable中,继而被映射到运行时常量池中。所以直接采用ldc指令将它从ConstantPool中取出来,塞进操作数栈中了。
相关解析代码参见:
case JVM_CONSTANT_Utf⑧ : { cfs->guarantee_more(② · CHECK); // utf⑧_length u② utf⑧_length = cfs->get_u②_fast(); u①* utf⑧_buffer = cfs->get_u①_buffer(); assert(utf⑧_buffer != NULL, \"null utf⑧ buffer\"); // Got utf⑧ string, guarantee utf⑧_length+① bytes, set stream position forward. cfs->guarantee_more(utf⑧_length+① · CHECK); // utf⑧ string, tag/access_flags cfs->skip_u①_fast(utf⑧_length); // Before storing the symbol, make sure it\'s legal if (_need_verify) { verify_legal_utf⑧((unsigned char*)utf⑧_buffer, utf⑧_length, CHECK); } if (EnableInvokeDynamic guarantee_property(java_lang_String::is_instance(patch()), \"Illegal utf⑧ patch at %d in class file %s\", index, CHECK); char* str = java_lang_String::as_utf⑧_string(patch()); // (could use java_lang_String::as_symbol instead, but might as well batch them) utf⑧_buffer = (u①*) str; utf⑧_length = (int) strlen(str); } unsigned int hash; Symbol* result = SymbolTable::lookup_only((char*)utf⑧_buffer, utf⑧_length, hash); if (result == NULL) { names[names_count] = (char*)utf⑧_buffer; lengths[names_count] = utf⑧_length; indices[names_count] = index; hashValues[names_count++] = hash; if (names_count == SymbolTable::symbol_alloc_batch_size) { SymbolTable::new_symbols(_loader_data, _cp, names_count, names, lengths, indices, hashValues, CHECK); names_count = ⓪; } } else { _cp->symbol_at_put(index, result); } }
当然这里仅仅是创建了①个Symbol对象,并不是我们需要的String对象,那么String对象从何而来呢?原来ldc指令将该常量push进操作数栈之前,会先根据ldc的指令参数index,找到SymbolTable中对应tag的Symbol对象,然后通过StringTable::intern将它转换成java_lang_String类型的字符串对象的。
下面给出这段逻辑在HotSpot VM上的实现:
CASE(_ldc):{// ...ignore... case JVM_CONSTANT_String: { oop result = constants->resolved_references()->obj_at(index); if (result == NULL) { CALL_VM(InterpreterRuntime::resolve_ldc(THREAD, (Bytecodes::Code) opcode), handle_exception); SET_STACK_OBJECT(THREAD->vm_result(), ⓪); THREAD->set_vm_result(NULL); } else { VERIFY_OOP(result); SET_STACK_OBJECT(result, ⓪); } break; }// ...ignore...}
-----------------------------------------------------------
oop Bytecode_loadconstant::resolve_constant(TRAPS) const { assert(_method.not_null(), \"must supply method to resolve constant\"); int index = raw_index(); ConstantPool* constants = _method->constants(); if (has_cache_index()) { return constants->resolve_cached_constant_at(index, THREAD); } else { return constants->resolve_constant_at(index, THREAD); }}
-----------------------------------------------------------
// Resolve late bound constants. oop resolve_constant_at(int index, TRAPS) { constantPoolHandle h_this(THREAD, this); return resolve_constant_at_impl(h_this, index, _no_index_sentinel, THREAD); }
-----------------------------------------------------------
// Called to resolve constants in the constant pool and return an oop.// Some constant pool entries cache their resolved oop. This is also// called to create oops from constants to use in arguments for invokedynamicoop ConstantPool::resolve_constant_at_impl(constantPoolHandle this_oop, int index, int cache_index, TRAPS) {// ...ignore... case JVM_CONSTANT_String: assert(cache_index != _no_index_sentinel, \"should have been set\"); if (this_oop->is_pseudo_string_at(index)) { result_oop = this_oop->pseudo_string_at(index, cache_index); break; } result_oop = string_at_impl(this_oop, index, cache_index, CHECK_NULL); break;// ...ignore...}
-----------------------------------------------------------
oop ConstantPool::string_at_impl(constantPoolHandle this_oop, int which, int obj_index, TRAPS) { // If the string has already been interned, this entry will be non-null oop str = this_oop->resolved_references()->obj_at(obj_index); if (str != NULL) return str; Symbol* sym = this_oop->unresolved_string_at(which); str = StringTable::intern(sym, CHECK_(NULL)); this_oop->string_at_put(which, obj_index, str); assert(java_lang_String::is_instance(str), \"must be string\"); return str;}
-----------------------------------------------------------
oop StringTable::intern(Symbol* symbol, TRAPS) { if (symbol == NULL) return NULL; ResourceMark rm(THREAD); int length; jchar* chars = symbol->as_unicode(length); Handle string; oop result = intern(string, chars, length, CHECK_NULL); return result;}
-----------------------------------------------------------
oop StringTable::intern(Handle string_or_null, jchar* name, int len, TRAPS) { unsigned int hashValue = hash_string(name, len); int index = the_table()->hash_to_index(hashValue); oop found_string = the_table()->lookup(index, name, len, hashValue); // Found if (found_string != NULL) return found_string; debug_only(StableMemoryChecker smc(name, len * sizeof(name[⓪]))); assert(!Universe::heap()->is_in_reserved(name), \"proposed name of symbol must be stable\"); Handle string; // try to reuse the string if possible if (!string_or_null.is_null()) { string = string_or_null; } else { string = java_lang_String::create_from_unicode(name, len, CHECK_NULL); } // Grab the StringTable_lock before getting the_table() because it could // change at safepoint. MutexLocker ml(StringTable_lock, THREAD); // Otherwise, add to symbol to table return the_table()->basic_add(index, string, name, len, hashValue, CHECK_NULL);}
-----------------------------------------------------------
Handle java_lang_String::create_from_unicode(jchar* unicode, int length, TRAPS) { Handle h_obj = basic_create(length, CHECK_NH); typeArrayOop buffer = value(h_obj()); for (int index = ⓪; index < length; index++) { buffer->char_at_put(index, unicode[index]); } return h_obj;}
编后语:关于《问一个比较小白的问题java中for循环里面new一个数组?jvm字符串的创建指令的问题》关于知识就介绍到这里,希望本站内容能让您有所收获,如有疑问可跟帖留言,值班小编第一时间回复。 下一篇内容是有关《卡地亚手表维修价格一般多高?我想组装个电脑主机2000左右的》,感兴趣的同学可以点击进去看看。
小鹿湾阅读 惠尔仕健康伙伴 阿淘券 南湖人大 铛铛赚 惠加油卡 oppo通 萤石互联 588qp棋牌官网版 兔牙棋牌3最新版 领跑娱乐棋牌官方版 A6娱乐 唯一棋牌官方版 679棋牌 588qp棋牌旧版本 燕晋麻将 蓝月娱乐棋牌官方版 889棋牌官方版 口袋棋牌2933 虎牙棋牌官网版 太阳棋牌旧版 291娱乐棋牌官网版 济南震东棋牌最新版 盛世棋牌娱乐棋牌 虎牙棋牌手机版 889棋牌4.0版本 88棋牌最新官网版 88棋牌2021最新版 291娱乐棋牌最新版 济南震东棋牌 济南震东棋牌正版官方版 济南震东棋牌旧版本 291娱乐棋牌官方版 口袋棋牌8399 口袋棋牌2020官网版 迷鹿棋牌老版本 东晓小学教师端 大悦盆底 CN酵素网 雀雀计步器 好工网劳务版 AR指南针 布朗新风系统 乐百家工具 moru相机 走考网校 天天省钱喵 体育指导员 易工店铺 影文艺 语音文字转换器