简体   繁体   English

JVM如何分配此内存

[英]How does JVM allocate this memory

If you declare an array of strings in java like this 如果您在Java中像这样声明字符串数组

String[] words;

That just gives you a reference correct? 那只是给您一个正确的参考?

now, I am coming from a background in C, so I know that an array of "strings" in C are pointers to pointers, or an array of arrays. 现在,我来自C语言的背景,所以我知道C语言中的“字符串”数组是指向指针的指针,或者是数组的数组。 However, I am wondering how JVM uses this declaration... Is it just a single reference? 但是,我想知道JVM如何使用此声明...它只是一个引用吗? Then when you give it sufficient memory, it will give the strings different lengths as well? 然后,当您给它足够的内存时,它也会为字符串提供不同的长度吗?

It's kind of hard for me to describe but I know that Strings are just arrays of characters, so how does the JVM determine how long the strings are before allocating it? 我很难形容,但我知道字符串只是字符数组,因此JVM如何在分配字符串之前确定字符串有多长时间? Does it reallocate a whole new array of strings with a new updated string length. 它是否以新的更新字符串长度重新分配整个字符串数组。

char array[6][6]; //in C this is necessary because it needs to know the column and row length

similar to this 与此类似

char* array[5]; // you still need to malloc the slots in the array for a two dimensional length to be achieved

but in java I dont get how this can work 但是在Java中我不知道它如何工作

  String line = null;
    try {
        while ((line = bfr.readLine()) != null) {
            if (StringUtils.isBlank(line))
                continue;

            System.out.println(line);
            String[] chunks = line.split(","); //this line right here, how does JVM allocate proper memory
            MindsparkPartnerCode record = new MindsparkPartnerCode();

            record.setIEFFCode(chunks[0]);
            records.add(record);

Well, you're really asking two questions here. 好吧,您实际上是在问两个问题。

First of all, declaring an array (of any depth) doesn't allocate memory in Java, whereas in your C example you're declaring and defining an array, which does allocate memory. 首先,在Java中声明一个数组(任何深度)都不会分配内存,而在您的C示例中,您声明定义了一个数组,它分配内存。

Java: Java:

String[] words; // Just a reference (null at this point) -- no memory allocated

C: C:

char array[6][10]; // *Does* allocate 60 bytes of memory, usually on the stack.

In Java, no memory is ever allocated until the new operator is used (except, of course, for primitives). 在Java中,在使用new运算符之前,不会分配任何内存(当然,对于基元除外)。

Foo bar; // Just a reference
bar = new Foo(); // NOW memory has been allocated.

new returns a reference to a new object. new返回对新对象的引用 Think of everything that isn't a primitive as a reference (this includes arrays!). 将不是原始元素的所有内容都视为参考(包括数组!)。


Strings are no different. 字符串没有什么不同。

String[] foo;

... is just a reference to an array of String object references . ...只是为字符串对象引用的数组引用 Nothing more. 而已。

Even when you create the array... 即使您创建数组...

foo = new String[20];

... Java allocates 20 * sizeof(JavaReference) bytes (where JavaReference is whatever underlying type the JVM is using to represent references). ... Java分配20 * sizeof(JavaReference)字节(其中JavaReference是JVM用于表示引用的任何基础类型)。 Therefore, the size of the array is now known . 因此,现在知道数组的大小。

When you actually add strings to that array... 当您实际将字符串添加到该数组时...

foo[0] = "Hello!"; // Which is essentially...
foo[0] = new String("Hello!");

... THAT is when you're telling the JVM how long your string is, thus telling it to allocate (strlen("Hello!") + 1) * 2 bytes (since Java stores its strings in UTF-16 encoding). ...... 就是当你告诉你的JVM字符串有多长,从而告诉它分配(strlen("Hello!") + 1) * 2个字节(因为Java的存储其字符串以UTF-16编码)。

As well, remember that strings are immutable , so the JVM doesn't have to worry about realloc 'ing them. 还有,请记住, 字符串是不可变的,所以JVM不必担心realloc “荷兰国际集团他们。


Your question about strings is tricky with Java since Java takes what is otherwise just another class ( String ) and turns it into a language construct (as seen in that last code example). 关于Java,关于字符串的问题很棘手,因为Java接受了另外一个类( String ),然后将其转换为语言结构(如最后一个代码示例所示)。 It's no wonder strings can be confusing when thinking in terms of memory and allocation. 难怪在考虑内存和分配时字符串会造成混乱。

In Java a String is not an array of characters. 在Java中, String不是字符数组。 it is a reference to garbage-collected instance of a class java.lang.String on the heap. 它是对堆上类java.lang.String垃圾回收实例的引用。 From the docs: 从文档:

The String class represents character strings. String类表示字符串。 All string literals in Java programs, such as "abc", are implemented as instances of this class. Java程序中的所有字符串文字(例如“ abc”)都实现为此类的实例。

Strings are constant; 字符串是常量; their values cannot be changed after they are created. 它们的值创建后无法更改。 String buffers support mutable strings. 字符串缓冲区支持可变字符串。 Because String objects are immutable they can be shared. 由于String对象是不可变的,因此可以共享它们。 For example: 例如:

  String str = "abc"; 

is equivalent to: 等效于:

  char data[] = {'a', 'b', 'c'}; String str = new String(data); 

The class String includes methods for examining individual characters of the sequence, for comparing strings, for searching strings, for extracting substrings, and for creating a copy of a string with all characters translated to uppercase or to lowercase. String类包含一些方法,这些方法可以检查序列中的各个字符,比较字符串,搜索字符串,提取子字符串以及创建字符串的副本,并将所有字符都转换为大写或小写。 Case mapping is based on the Unicode Standard version specified by the Character class. 大小写映射基于Character类指定的Unicode标准版本。

The Java language provides special support for the string concatenation operator ( + ), and for conversion of other objects to strings. Java语言为字符串连接运算符(+)以及将其他对象转换为字符串提供了特殊的支持。 String concatenation is implemented through the StringBuilder(or StringBuffer) class and its append method. 字符串连接是通过StringBuilder(或StringBuffer)类及其append方法实现的。 String conversions are implemented through the method toString, defined by Object and inherited by all classes in Java... 字符串转换是通过toString方法实现的,该方法由Object定义并由Java中的所有类继承...

Thus a String can be created from an array of characters, but it is more than an array of characters. 因此可以从一个字符数组创建一个String ,但它不仅仅是一个字符数组。 This class is built into Java itself, so the compiler knows how to instantiate instances of this class from string literals typed into your code. 该类内置于Java本身,因此编译器知道如何从键入代码的字符串文字中实例化该类的实例。

Thus when you do something like: 因此,当您执行以下操作时:

String[] chunks = line.split(",");

you are calling the method split on an instance of the class java.lang.String . 您在类java.lang.String的实例上调用split方法。 It returns to you array of java.lang.String objects which it allocates itself (both the array and the strings). 它返回给您一个java.lang.String对象数组, 对象将自己分配 (数组和字符串)。 Eventually these will all be garbage collected when they are no longer referenced. 最终,当它们不再被引用时,将全部被垃圾回收。

 String[] chunks = line.split(","); //this line right here, how does JVM allocate proper memory

By the time this statement is complete, there will be N+1 new objects you can reference: 在此语句完成时,将可以引用N + 1个新对象:

  • One String[] array object 一个String[]数组对象
  • N String objects, one sitting in each slot in the array N个String对象,每个对象位于数组的每个插槽中

I have some C background as well. 我也有一些C背景。 In Java an array of something is quite the same as in C. Its an array of pointers (or just base types like ints). 在Java中,某些事物的数组与C中的完全相同。它是一个指针数组(或仅是基本类型(如ints))。 The size of the array must be available to Java as well like in 数组的大小必须对Java一样可用,例如

String[] words = new String[10];

Your example declared words as an array of strings resulting in the variable 'words' with a null pointer to an array of string. 您的示例将单词声明为字符串数组,从而导致变量“ words”具有指向字符串数组的空指针。 My example will point 'words' to an array of 10 pointers to strings. 我的示例将“单词”指向由10个指向字符串的指针组成的数组。

Have a look at the API java.util.arrays 看看API java.util.arrays

https://docs.oracle.com/javase/8/docs/api/java/util/Arrays.html https://docs.oracle.com/javase/8/docs/api/java/util/Arrays.html

It allocates an array of references to other heap objects. 它为其他堆对象分配一个引用数组。 A capital-S String in Java is itself a reference to an object on the heap, which in turn contains a reference to a char[], which may have arbitrary size. Java中的大写S字符串本身就是对堆上对象的引用,而该对象又包含对char []的引用,该char []可以具有任意大小。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM