diff --git a/1-js/04-object-basics/03-garbage-collection/article.md b/1-js/04-object-basics/03-garbage-collection/article.md index 72e30469c..047ab582f 100644 --- a/1-js/04-object-basics/03-garbage-collection/article.md +++ b/1-js/04-object-basics/03-garbage-collection/article.md @@ -1,38 +1,38 @@ -# Garbage collection +# Thu gom rác -Memory management in JavaScript is performed automatically and invisibly to us. We create primitives, objects, functions... All that takes memory. +Quản lý bộ nhớ trong JavaScript được thực hiện tự động và vô hình đối với chúng ta. Chúng ta tạo các nguyên hàm, đối tượng, hàm... Tất cả những thứ đó cần bộ nhớ. -What happens when something is not needed any more? How does the JavaScript engine discover it and clean it up? +Điều gì xảy ra khi một cái gì đó không còn cần thiết nữa? Làm thế nào để JavaScript engine phát hiện ra nó và dọn sạch nó? -## Reachability +## Khả năng tiếp cận -The main concept of memory management in JavaScript is *reachability*. +Khái niệm chính về quản lý bộ nhớ trong JavaScript là *khả năng tiếp cận*. -Simply put, "reachable" values are those that are accessible or usable somehow. They are guaranteed to be stored in memory. +Nói một cách đơn giản, các giá trị "có thể tiếp cận" là những giá trị có thể truy cập hoặc sử dụng được bằng cách nào đó. Chúng được đảm bảo được lưu trữ trong bộ nhớ. -1. There's a base set of inherently reachable values, that cannot be deleted for obvious reasons. +1. Có một tập hợp cơ sở các giá trị vốn có thể truy cập được, không thể xóa vì những lý do rõ ràng. - For instance: + Ví dụ: - - The currently executing function, its local variables and parameters. - - Other functions on the current chain of nested calls, their local variables and parameters. - - Global variables. - - (there are some other, internal ones as well) + - Hàm hiện đang chạy, các biến cục bộ và tham số của nó. + - Các hàm khác trên chuỗi lệnh gọi lồng nhau hiện tại, các biến cục bộ và tham số của chúng. + - Biến chung. + - (có một số khác, cũng có nội bộ) - These values are called *roots*. + Những giá trị này được gọi là *gốc*. -2. Any other value is considered reachable if it's reachable from a root by a reference or by a chain of references. +2. Bất kỳ giá trị nào khác được coi là có thể truy cập được nếu giá trị đó có thể truy cập được từ gốc bằng tham chiếu hoặc chuỗi tham chiếu. - For instance, if there's an object in a global variable, and that object has a property referencing another object, *that* object is considered reachable. And those that it references are also reachable. Detailed examples to follow. + Chẳng hạn, nếu có một đối tượng trong một biến chung và đối tượng đó có một thuộc tính tham chiếu đến một đối tượng khác, thì đối tượng *đó* đó được coi là có thể truy cập được. Và những thứ mà nó tham chiếu cũng có thể truy cập được. Ví dụ chi tiết để làm theo. -There's a background process in the JavaScript engine that is called [garbage collector](https://en.wikipedia.org/wiki/Garbage_collection_(computer_science)). It monitors all objects and removes those that have become unreachable. +Có một quy trình nền trong JavaScript engine được gọi là [bộ gom rác](https://vi.wikipedia.org/wiki/Thu_gom_rác_(khoa_học_máy_tính)). Nó giám sát tất cả các đối tượng và loại bỏ những đối tượng không thể truy cập được. -## A simple example +## Một ví dụ đơn giản -Here's the simplest example: +Đây là ví dụ đơn giản nhất: ```js -// user has a reference to the object +// người dùng có một tham chiếu đến đối tượng let user = { name: "John" }; @@ -40,9 +40,9 @@ let user = { ![](memory-user-john.svg) -Here the arrow depicts an object reference. The global variable `"user"` references the object `{name: "John"}` (we'll call it John for brevity). The `"name"` property of John stores a primitive, so it's painted inside the object. +Ở đây mũi tên mô tả một tham chiếu đối tượng. Biến chung `"user"` tham chiếu đối tượng `{name: "John"}` (chúng ta sẽ gọi nó là John cho ngắn gọn). Thuộc tính `"name"` của John lưu trữ một nguyên hàm, do đó, nó được vẽ bên trong đối tượng. -If the value of `user` is overwritten, the reference is lost: +Nếu giá trị của `user` bị ghi đè, tham chiếu sẽ bị mất: ```js user = null; @@ -50,14 +50,14 @@ user = null; ![](memory-user-john-lost.svg) -Now John becomes unreachable. There's no way to access it, no references to it. Garbage collector will junk the data and free the memory. +Bây giờ John trở nên không thể truy cập được. Không có cách nào để truy cập nó, không có tham chiếu đến nó. Trình thu gom rác sẽ loại bỏ dữ liệu và giải phóng bộ nhớ. -## Two references +## Hai tham chiếu -Now let's imagine we copied the reference from `user` to `admin`: +Bây giờ, hãy tưởng tượng chúng ta đã sao chép tham chiếu từ `user` sang `admin`: ```js -// user has a reference to the object +// người dùng có một tham chiếu đến đối tượng let user = { name: "John" }; @@ -69,16 +69,16 @@ let admin = user; ![](memory-user-john-admin.svg) -Now if we do the same: +Bây giờ nếu chúng ta làm như vậy: ```js user = null; ``` -...Then the object is still reachable via `admin` global variable, so it's in memory. If we overwrite `admin` too, then it can be removed. +...Sau đó, đối tượng vẫn có thể truy cập được thông qua biến chung `admin`, vì vậy nó phải ở trong bộ nhớ. Nếu chúng ta ghi đè lên `admin`, thì nó có thể bị xóa. -## Interlinked objects +## Các đối tượng liên kết với nhau -Now a more complex example. The family: +Bây giờ là một ví dụ phức tạp hơn. Gia đình: ```js function marry(man, woman) { @@ -98,15 +98,15 @@ let family = marry({ }); ``` -Function `marry` "marries" two objects by giving them references to each other and returns a new object that contains them both. +Hàm `marry` "kết hôn" hai đối tượng bằng cách cho chúng tham chiếu lẫn nhau và trả về một đối tượng mới chứa cả hai đối tượng. -The resulting memory structure: +Cấu trúc bộ nhớ kết quả: ![](family.svg) -As of now, all objects are reachable. +Hiện tại, tất cả các đối tượng đều có thể truy cập được. -Now let's remove two references: +Bây giờ hãy xóa hai tham chiếu: ```js delete family.father; @@ -115,98 +115,98 @@ delete family.mother.husband; ![](family-delete-refs.svg) -It's not enough to delete only one of these two references, because all objects would still be reachable. +Chỉ xóa một trong hai tham chiếu này là không đủ, bởi vì tất cả các đối tượng vẫn có thể truy cập được. -But if we delete both, then we can see that John has no incoming reference any more: +Nhưng nếu chúng ta xóa cả hai, thì chúng ta có thể thấy rằng John không còn tham chiếu nào nữa: ![](family-no-father.svg) -Outgoing references do not matter. Only incoming ones can make an object reachable. So, John is now unreachable and will be removed from the memory with all its data that also became unaccessible. +Tham chiếu gửi đi không quan trọng. Chỉ những cái đến mới có thể làm cho một đối tượng có thể truy cập được. Vì vậy, John hiện không thể truy cập được và sẽ bị xóa khỏi bộ nhớ cùng với tất cả dữ liệu của nó cũng không thể truy cập được. -After garbage collection: +Sau khi thu gom rác: ![](family-no-father-2.svg) -## Unreachable island +## Đối tượng không thể tiếp cận -It is possible that the whole island of interlinked objects becomes unreachable and is removed from the memory. +Có thể toàn bộ các đối tượng được liên kết với nhau trở nên không thể truy cập được và bị xóa khỏi bộ nhớ. -The source object is the same as above. Then: +Đối tượng nguồn giống như trên. Sau đó: ```js family = null; ``` -The in-memory picture becomes: +Hình ảnh trong bộ nhớ trở thành: ![](family-no-family.svg) -This example demonstrates how important the concept of reachability is. +Ví dụ này cho thấy tầm quan trọng của khái niệm khả năng tiếp cận. -It's obvious that John and Ann are still linked, both have incoming references. But that's not enough. +Rõ ràng là John và Ann vẫn được liên kết với nhau, cả hai đều có tham chiếu sắp tới. Nhưng điều đó là không đủ. -The former `"family"` object has been unlinked from the root, there's no reference to it any more, so the whole island becomes unreachable and will be removed. +Đối tượng `"family"` trước đây đã bị hủy liên kết khỏi thư mục gốc, không còn tham chiếu đến nó nữa, vì vậy toàn bộ đối tượng trở nên không thể truy cập được và sẽ bị xóa. -## Internal algorithms +## Thuật toán nội bộ -The basic garbage collection algorithm is called "mark-and-sweep". +Thuật toán thu gom rác cơ bản được gọi là "đánh dấu và quét". -The following "garbage collection" steps are regularly performed: +Các bước "thu gom rác" sau đây được thực hiện thường xuyên: -- The garbage collector takes roots and "marks" (remembers) them. -- Then it visits and "marks" all references from them. -- Then it visits marked objects and marks *their* references. All visited objects are remembered, so as not to visit the same object twice in the future. -- ...And so on until every reachable (from the roots) references are visited. -- All objects except marked ones are removed. +- Bộ gom rác lấy gốc và "đánh dấu" (ghi nhớ) chúng. +- Sau đó, nó truy cập và "đánh dấu" tất cả các tham chiếu từ chúng. +- Sau đó, nó truy cập các đối tượng được đánh dấu và đánh dấu các tham chiếu *của chúng*. Tất cả các đối tượng đã truy cập đều được ghi nhớ để không truy cập cùng một đối tượng hai lần trong tương lai. +- ...Và cứ như vậy cho đến khi mọi tham chiếu có thể truy cập (từ gốc) đều được truy cập. +- Tất cả các đối tượng trừ những đối tượng được đánh dấu đều bị xóa. -For instance, let our object structure look like this: +Chẳng hạn, hãy để cấu trúc đối tượng của chúng ta trông như thế này: ![](garbage-collection-1.svg) -We can clearly see an "unreachable island" to the right side. Now let's see how "mark-and-sweep" garbage collector deals with it. +Chúng ta có thể thấy rõ ràng một "đối tượng không thể tiếp cận" ở phía bên phải. Bây giờ hãy xem bộ gom rác "đánh dấu và quét" xử lý nó như thế nào. -The first step marks the roots: +Bước đầu tiên đánh dấu gốc: ![](garbage-collection-2.svg) -Then their references are marked: +Sau đó, chúng ta theo dõi các tham chiếu của chúng và đánh dấu các đối tượng được tham chiếu: ![](garbage-collection-3.svg) -...And their references, while possible: +...Và tiếp tục đi theo các tham chiếu khác, nếu có thể: ![](garbage-collection-4.svg) -Now the objects that could not be visited in the process are considered unreachable and will be removed: +Bây giờ các đối tượng không thể truy cập được trong quy trình được coi là không thể truy cập và sẽ bị xóa: ![](garbage-collection-5.svg) -We can also imagine the process as spilling a huge bucket of paint from the roots, that flows through all references and marks all reachable objects. The unmarked ones are then removed. +Chúng ta cũng có thể tưởng tượng quá trình này giống như đổ một thùng sơn khổng lồ từ gốc, chảy qua tất cả các tham chiếu và đánh dấu tất cả các đối tượng có thể tiếp cận. Những cái không được đánh dấu sau đó được loại bỏ. -That's the concept of how garbage collection works. JavaScript engines apply many optimizations to make it run faster and not affect the execution. +Đó là khái niệm về cách hoạt động của thu gom rác. Các JavaScript engine áp dụng nhiều tối ưu hóa để làm cho nó chạy nhanh hơn và không gây ra bất kỳ sự chậm trễ nào trong quá trình thực thi mã. -Some of the optimizations: +Một số tối ưu hóa: -- **Generational collection** -- objects are split into two sets: "new ones" and "old ones". Many objects appear, do their job and die fast, they can be cleaned up aggressively. Those that survive for long enough, become "old" and are examined less often. -- **Incremental collection** -- if there are many objects, and we try to walk and mark the whole object set at once, it may take some time and introduce visible delays in the execution. So the engine tries to split the garbage collection into pieces. Then the pieces are executed one by one, separately. That requires some extra bookkeeping between them to track changes, but we have many tiny delays instead of a big one. -- **Idle-time collection** -- the garbage collector tries to run only while the CPU is idle, to reduce the possible effect on the execution. +- **Thu gom thế hệ** -- các đối tượng được chia thành hai bộ: "bộ mới" và "bộ cũ". Trong mã điển hình, nhiều đối tượng có tuổi thọ ngắn: chúng xuất hiện, thực hiện công việc của mình và chết nhanh chóng, vì vậy, việc theo dõi các đối tượng mới và xóa bộ nhớ khỏi chúng là điều hợp lý nếu đúng như vậy. Những đối tượng tồn tại đủ lâu, trở nên "già" và ít được kiểm tra thường xuyên hơn. +- **Thu gom gia tăng** -- nếu có nhiều đối tượng và chúng ta cố gắng đi bộ và đánh dấu toàn bộ đối tượng cùng một lúc, có thể mất một chút thời gian và gây ra sự chậm trễ có thể nhìn thấy trong quá trình thực thi. Vì vậy, engine chia toàn bộ tập hợp các đối tượng hiện có thành nhiều phần. Và sau đó lần lượt xóa các phần này. Có nhiều bộ thu gom rác nhỏ thay vì một bộ lớn. Điều đó đòi hỏi một số kế toán bổ sung giữa chúng để theo dõi các thay đổi, nhưng chúng tôi nhận được nhiều sự chậm trễ nhỏ thay vì một sự chậm trễ lớn. +- **Thu gom vào thời gian nhàn rỗi** -- bộ thu gom rác cố gắng chỉ chạy khi CPU không hoạt động, để giảm tác động có thể có đối với quá trình thực thi. -There exist other optimizations and flavours of garbage collection algorithms. As much as I'd like to describe them here, I have to hold off, because different engines implement different tweaks and techniques. And, what's even more important, things change as engines develop, so studying deeper "in advance", without a real need is probably not worth that. Unless, of course, it is a matter of pure interest, then there will be some links for you below. +Có tồn tại các tối ưu hóa và hương vị khác của thuật toán thu gom rác. Tôi muốn mô tả thêm nhiều nữa nhưng tôi phải dừng lại, bởi vì các engine khác nhau thực hiện các chỉnh sửa và kỹ thuật khác nhau. Và, điều quan trọng hơn nữa, mọi thứ thay đổi khi engine phát triển, vì vậy việc nghiên cứu sâu hơn "trước", nếu không có nhu cầu thực sự có lẽ không đáng. Tất nhiên, trừ khi đó là vấn đề hoàn toàn vì lợi ích, khi đó sẽ có một số liên kết dành cho bạn bên dưới. -## Summary +## Tóm tắt -The main things to know: +Những điều chính cần biết: -- Garbage collection is performed automatically. We cannot force or prevent it. -- Objects are retained in memory while they are reachable. -- Being referenced is not the same as being reachable (from a root): a pack of interlinked objects can become unreachable as a whole. +- Việc thu gom rác được thực hiện tự động. Chúng ta không thể ép buộc hay ngăn cản. +- Các đối tượng được giữ lại trong bộ nhớ trong khi chúng có thể truy cập được. +- Được tham chiếu không giống như có thể truy cập được (từ gốc): một gói các đối tượng được liên kết với nhau có thể trở nên không thể truy cập được như một tổng thể, như chúng ta đã thấy trong ví dụ trên. -Modern engines implement advanced algorithms of garbage collection. +Các engine hiện đại thực hiện các thuật toán thu gom rác tiên tiến. -A general book "The Garbage Collection Handbook: The Art of Automatic Memory Management" (R. Jones et al) covers some of them. +Một cuốn sách chung "The Garbage Collection Handbook: The Art of Automatic Memory Management" (R. Jones et al) đề cập đến một số trong số chúng. -If you are familiar with low-level programming, the more detailed information about V8 garbage collector is in the article [A tour of V8: Garbage Collection](http://jayconrod.com/posts/55/a-tour-of-v8-garbage-collection). +Nếu bạn đã quen với lập trình cấp thấp, thông tin chi tiết hơn về bộ thu gom rác của V8 có trong bài viết [Chuyến tham quan V8: Thu gom rác](https://jayconrod.com/posts/55/a-tour-of-v8-garbage-collection). -[V8 blog](https://v8.dev/) also publishes articles about changes in memory management from time to time. Naturally, to learn the garbage collection, you'd better prepare by learning about V8 internals in general and read the blog of [Vyacheslav Egorov](http://mrale.ph) who worked as one of V8 engineers. I'm saying: "V8", because it is best covered with articles in the internet. For other engines, many approaches are similar, but garbage collection differs in many aspects. +[Blog V8](https://v8.dev/) thỉnh thoảng cũng xuất bản các bài viết về những thay đổi trong quản lý bộ nhớ. Đương nhiên, để tìm hiểu thêm về thu gom rác, tốt hơn hết bạn nên chuẩn bị bằng cách tìm hiểu về các bộ phận bên trong engine V8 nói chung và đọc blog của [Vyacheslav Egorov](https://mrale.ph), người từng là một trong những kỹ sư của engine V8. Tôi đang nói: "V8", bởi vì nó được đề cập tốt nhất bởi các bài báo trên internet. Đối với các công cụ khác, nhiều cách tiếp cận tương tự nhau, nhưng việc thu gom rác khác nhau ở nhiều khía cạnh. -In-depth knowledge of engines is good when you need low-level optimizations. It would be wise to plan that as the next step after you're familiar with the language. +Kiến thức chuyên sâu về các công cụ rất hữu ích khi bạn cần tối ưu hóa ở mức độ thấp. Sẽ là khôn ngoan nếu bạn lên kế hoạch cho bước tiếp theo sau khi bạn đã quen thuộc với ngôn ngữ này. diff --git a/1-js/04-object-basics/03-garbage-collection/family-delete-refs.svg b/1-js/04-object-basics/03-garbage-collection/family-delete-refs.svg index a582ca64b..6754a3922 100644 --- a/1-js/04-object-basics/03-garbage-collection/family-delete-refs.svg +++ b/1-js/04-object-basics/03-garbage-collection/family-delete-refs.svg @@ -1 +1 @@ -<global variable>ObjectObjectwifefamilyname: "John"name: "Ann"motherObjectfatherhusband \ No newline at end of file +<biến chung>Đối tượngĐối tượngvợgia đìnhname: "John"name: "Ann"mẹĐối tượngbốchồng diff --git a/1-js/04-object-basics/03-garbage-collection/family-no-family.svg b/1-js/04-object-basics/03-garbage-collection/family-no-family.svg index c73dd6a48..daa43f415 100644 --- a/1-js/04-object-basics/03-garbage-collection/family-no-family.svg +++ b/1-js/04-object-basics/03-garbage-collection/family-no-family.svg @@ -1 +1 @@ -<global>ObjectObjectfatherwifename: "John"name: "Ann"motherObjecthusbandfamily: null \ No newline at end of file +<chung>Đối tượngĐối tượngbốvợname: "John"name: "Ann"mẹĐối tượngchồngfamily: null diff --git a/1-js/04-object-basics/03-garbage-collection/family-no-father-2.svg b/1-js/04-object-basics/03-garbage-collection/family-no-father-2.svg index 6bd13c0e8..fe69d7eef 100644 --- a/1-js/04-object-basics/03-garbage-collection/family-no-father-2.svg +++ b/1-js/04-object-basics/03-garbage-collection/family-no-father-2.svg @@ -1 +1 @@ -Objectfamilyname: "Ann"motherObject<global> \ No newline at end of file +Đối tượnggia đìnhname: "Ann"mẹĐối tượng<chung> diff --git a/1-js/04-object-basics/03-garbage-collection/family-no-father.svg b/1-js/04-object-basics/03-garbage-collection/family-no-father.svg index fd1f20607..5b7e7fb1b 100644 --- a/1-js/04-object-basics/03-garbage-collection/family-no-father.svg +++ b/1-js/04-object-basics/03-garbage-collection/family-no-father.svg @@ -1 +1 @@ -ObjectObjectwifefamilyname: "John"name: "Ann"motherObject<global> \ No newline at end of file +Đối tượngĐối tượngvợgia đìnhname: "John"name: "Ann"mẹĐối tượng<chung> diff --git a/1-js/04-object-basics/03-garbage-collection/family.svg b/1-js/04-object-basics/03-garbage-collection/family.svg index fd0534874..cc99443a1 100644 --- a/1-js/04-object-basics/03-garbage-collection/family.svg +++ b/1-js/04-object-basics/03-garbage-collection/family.svg @@ -1 +1 @@ -ObjectObjectfatherwifefamilyname: "John"name: "Ann"motherObjecthusband<global variable> \ No newline at end of file +Đối tượngĐối tượngbốvợgia đìnhname: "John"name: "Ann"mẹĐối tượngchồng<biến chung> diff --git a/1-js/04-object-basics/03-garbage-collection/garbage-collection-1.svg b/1-js/04-object-basics/03-garbage-collection/garbage-collection-1.svg index 5cac52e9a..3fc95afd4 100644 --- a/1-js/04-object-basics/03-garbage-collection/garbage-collection-1.svg +++ b/1-js/04-object-basics/03-garbage-collection/garbage-collection-1.svg @@ -1 +1 @@ -<global> \ No newline at end of file +<chung> diff --git a/1-js/04-object-basics/03-garbage-collection/garbage-collection-2.svg b/1-js/04-object-basics/03-garbage-collection/garbage-collection-2.svg index 7dd3a693a..395bd596b 100644 --- a/1-js/04-object-basics/03-garbage-collection/garbage-collection-2.svg +++ b/1-js/04-object-basics/03-garbage-collection/garbage-collection-2.svg @@ -1 +1 @@ -<global> \ No newline at end of file +<chung> diff --git a/1-js/04-object-basics/03-garbage-collection/garbage-collection-3.svg b/1-js/04-object-basics/03-garbage-collection/garbage-collection-3.svg index 106057787..b60e1f526 100644 --- a/1-js/04-object-basics/03-garbage-collection/garbage-collection-3.svg +++ b/1-js/04-object-basics/03-garbage-collection/garbage-collection-3.svg @@ -1 +1 @@ -<global> \ No newline at end of file +<chung> diff --git a/1-js/04-object-basics/03-garbage-collection/garbage-collection-4.svg b/1-js/04-object-basics/03-garbage-collection/garbage-collection-4.svg index bd485adee..47c758e5a 100644 --- a/1-js/04-object-basics/03-garbage-collection/garbage-collection-4.svg +++ b/1-js/04-object-basics/03-garbage-collection/garbage-collection-4.svg @@ -1 +1 @@ -<global> \ No newline at end of file +<chung> diff --git a/1-js/04-object-basics/03-garbage-collection/garbage-collection-5.svg b/1-js/04-object-basics/03-garbage-collection/garbage-collection-5.svg index 2d85432bc..73870fdf7 100644 --- a/1-js/04-object-basics/03-garbage-collection/garbage-collection-5.svg +++ b/1-js/04-object-basics/03-garbage-collection/garbage-collection-5.svg @@ -1 +1 @@ -<global>unreachables \ No newline at end of file +<global>những thứ không thể truy cập diff --git a/1-js/04-object-basics/03-garbage-collection/memory-user-john-admin.svg b/1-js/04-object-basics/03-garbage-collection/memory-user-john-admin.svg index 191324354..c9db702cf 100644 --- a/1-js/04-object-basics/03-garbage-collection/memory-user-john-admin.svg +++ b/1-js/04-object-basics/03-garbage-collection/memory-user-john-admin.svg @@ -1 +1 @@ -username: "John"Objectadmin<global> \ No newline at end of file +username: "John"Đối tượngadmin<chung> diff --git a/1-js/04-object-basics/03-garbage-collection/memory-user-john-lost.svg b/1-js/04-object-basics/03-garbage-collection/memory-user-john-lost.svg index 07914a9ca..9702861cd 100644 --- a/1-js/04-object-basics/03-garbage-collection/memory-user-john-lost.svg +++ b/1-js/04-object-basics/03-garbage-collection/memory-user-john-lost.svg @@ -1 +1 @@ -name: "John"Objectuser: null<global> \ No newline at end of file +name: "John"Đối tượnguser: null<chung> diff --git a/1-js/04-object-basics/03-garbage-collection/memory-user-john.svg b/1-js/04-object-basics/03-garbage-collection/memory-user-john.svg index 15bd51afb..17a600376 100644 --- a/1-js/04-object-basics/03-garbage-collection/memory-user-john.svg +++ b/1-js/04-object-basics/03-garbage-collection/memory-user-john.svg @@ -1 +1 @@ -username: "John"Object<global> \ No newline at end of file +username: "John"Đối tượng<global>