text:
Điều trị bằng thuốc kháng HIV (thuốc điều trị ARV) sẽ làm chậm lại sự phát triển của virus HIV. Song, không giống các loại thuốc chữa bệnh khác, ARV chỉ là thuốc điều trị, chứ không chữa khỏi bệnh nên người có HIV phải uống thuốc suốt đời.
Thuốc ARV cũng là thuốc có nhiều tác dụng phụ nên không ít người đã bỏ dở giữa chừng. Tình trạng điều trị dở dang không những không giúp người bệnh khỏe lên mà còn nhanh đến với tử vong.
* Thuốc ARV kén người dùng
Theo bác sĩ Võ Kim Loan, Giám đốc Trung tâm phòng chống HIV/AIDS tỉnh, mục đích của việc điều trị bằng thuốc kháng HIV là ức chế sự nhân lên của virus và kìm hãm lượng virus trong máu ở mức thấp nhất. Ngoài ra, thuốc còn giúp phục hồi chức năng miễn dịch, giảm nguy cơ mắc các bệnh nhiễm trùng cơ hội, cải thiện chất lượng sống và tăng khả năng sống sót cho bệnh nhân.
Thuốc ARV là loại thuốc có rất nhiều độc tính nên không phải bệnh nhân nào cũng có thể sử dụng. Nếu điều trị dở dang, virus sẽ kháng thuốc làm bệnh nặng hơn và người bệnh tử vong nhanh hơn so với không điều trị bằng thuốc. Hiện trên địa bàn Đồng Nai mới chỉ có khoảng 40% số người điều trị HIV bằng ARV tuân thủ đầy đủ các chỉ định và có sự giám sát của ngành chức năng nhờ sự tự nguyện chấp nhận điều trị và hỗ trợ tích cực từ phía người thân.
* Những tác dụng không mong muốn
- Triệu chứng buồn nôn: Để hạn chế tác dụng phụ này, có thể uống thuốc trong bữa ăn. Tuy nhiên, đối với thuốc indinavir và didanosin, không nên dùng trong bữa ăn vì ảnh hưởng tới hấp thu và chuyển hóa thuốc.
- Tiêu chảy là triệu chứng rất thường gặp. Khi bị tiêu chảy cần bù nước điện giải đầy đủ bằng đường uống (oresol) hoặc đường truyền nếu nặng, có thể phải dùng các thuốc chống tiêu chảy để hạn chế tiêu chảy tạm thời.
- Đau đầu là chứng hay gặp khi trong phác đồ điều trị, có thể dùng thuốc giảm đau thông thường như paracetamol.
- Đau bụng, khó chịu ở bụng, nếu nặng cần đến gặp bác sĩ hoặc cơ sở cấp thuốc để được hướng dẫn thêm, thậm chí phải thay đổi phác đồ điều trị hoặc thay thế thuốc khác.
- Nổi ban đỏ, ngứa; rối loạn giấc ngủ…
- Một số người khi điều trị bằng ARV lại xuất hiện bệnh lý thần kinh ngoại biên như yếu đầu chi, đi lại khó khăn; viêm tụy; có hiện tượng tích mỡ và teo mỡ ở một vài nơi trên cơ thể; tăng men gan và gây độc cho gan; rối loại tâm thần, trầm cảm…
* Tuân thủ nghiêm ngặt khi dùng thuốc
Tuân thủ các quy định là yếu tố quyết định sự thành công trong điều trị HIV. Nghĩa là người bệnh phải thực hiện 3 đúng: đúng thuốc, đúng thời gian và đúng cách. Nếu quên thuốc quá 3 lần/tháng, điều trị coi như thất bại, người bệnh tử vong nhanh hơn so với những người không điều trị.
Trường hợp người bệnh khi phát hiện ra mình quên uống thuốc theo lịch thì phải uống ngay liều thuốc vừa quên. Tiếp theo tính thời gian uống liều kế tiếp theo lịch như thường lệ. Nếu thời gian đến liều uống kế tiếp còn dưới 4 tiếng thì không được uống liều kế tiếp theo lịch cũ mà phải đợi trên 4 tiếng sau mới được uống. Nếu quên hơn 2 liều trong một tuần, người bệnh phải báo cho bác sĩ điều trị để được hướng dẫn.
Phương Liễu (ghi)

markdown:
**Điều trị bằng thuốc kháng HIV (thuốc điều trị ARV) sẽ làm chậm lại sự phát triển của virus HIV. Song, không giống các loại thuốc chữa bệnh khác, ARV chỉ là thuốc điều trị, chứ không chữa khỏi bệnh nên người có HIV phải uống thuốc suốt đời.**
Thuốc ARV cũng là thuốc có nhiều tác dụng phụ nên không ít người đã bỏ dở giữa chừng. Tình trạng điều trị dở dang không những không giúp người bệnh khỏe lên mà còn nhanh đến với tử vong.
*** Thuốc ARV kén người dùng**
Theo bác sĩ Võ Kim Loan, Giám đốc Trung tâm phòng chống HIV/AIDS tỉnh, mục đích của việc điều trị bằng thuốc kháng HIV là ức chế sự nhân lên của virus và kìm hãm lượng virus trong máu ở mức thấp nhất. Ngoài ra, thuốc còn giúp phục hồi chức năng miễn dịch, giảm nguy cơ mắc các bệnh nhiễm trùng cơ hội, cải thiện chất lượng sống và tăng khả năng sống sót cho bệnh nhân.
|
|![]()
|Nhân viên Trung tâm phòng chống HIV/AIDS phân thuốc ARV để cấp cho bệnh nhân. Ảnh: P. Liễu|
Thuốc ARV là loại thuốc có rất nhiều độc tính nên không phải bệnh nhân nào cũng có thể sử dụng. Nếu điều trị dở dang, virus sẽ kháng thuốc làm bệnh nặng hơn và người bệnh tử vong nhanh hơn so với không điều trị bằng thuốc. Hiện trên địa bàn Đồng Nai mới chỉ có khoảng 40% số người điều trị HIV bằng ARV tuân thủ đầy đủ các chỉ định và có sự giám sát của ngành chức năng nhờ sự tự nguyện chấp nhận điều trị và hỗ trợ tích cực từ phía người thân.
*** Những tác dụng không mong muốn**
- Triệu chứng buồn nôn: Để hạn chế tác dụng phụ này, có thể uống thuốc trong bữa ăn. Tuy nhiên, đối với thuốc indinavir và didanosin, không nên dùng trong bữa ăn vì ảnh hưởng tới hấp thu và chuyển hóa thuốc.
- Tiêu chảy là triệu chứng rất thường gặp. Khi bị tiêu chảy cần bù nước điện giải đầy đủ bằng đường uống (oresol) hoặc đường truyền nếu nặng, có thể phải dùng các thuốc chống tiêu chảy để hạn chế tiêu chảy tạm thời.
- Đau đầu là chứng hay gặp khi trong phác đồ điều trị, có thể dùng thuốc giảm đau thông thường như paracetamol.
- Đau bụng, khó chịu ở bụng, nếu nặng cần đến gặp bác sĩ hoặc cơ sở cấp thuốc để được hướng dẫn thêm, thậm chí phải thay đổi phác đồ điều trị hoặc thay thế thuốc khác.
- Nổi ban đỏ, ngứa; rối loạn giấc ngủ…
- Một số người khi điều trị bằng ARV lại xuất hiện bệnh lý thần kinh ngoại biên như yếu đầu chi, đi lại khó khăn; viêm tụy; có hiện tượng tích mỡ và teo mỡ ở một vài nơi trên cơ thể; tăng men gan và gây độc cho gan; rối loại tâm thần, trầm cảm…
*** Tuân thủ nghiêm ngặt khi dùng thuốc**
Tuân thủ các quy định là yếu tố quyết định sự thành công trong điều trị HIV. Nghĩa là người bệnh phải thực hiện 3 đúng: đúng thuốc, đúng thời gian và đúng cách. Nếu quên thuốc quá 3 lần/tháng, điều trị coi như thất bại, người bệnh tử vong nhanh hơn so với những người không điều trị.
Trường hợp người bệnh khi phát hiện ra mình quên uống thuốc theo lịch thì phải uống ngay liều thuốc vừa quên. Tiếp theo tính thời gian uống liều kế tiếp theo lịch như thường lệ. Nếu thời gian đến liều uống kế tiếp còn dưới 4 tiếng thì không được uống liều kế tiếp theo lịch cũ mà phải đợi trên 4 tiếng sau mới được uống. Nếu quên hơn 2 liều trong một tuần, người bệnh phải báo cho bác sĩ điều trị để được hướng dẫn.
**Phương Liễu** (ghi)

Content-Type: text/html


text:
Váy liền Eva - Thời trang Hàn Quốc Giá 340.000đ
Giá bán: 340.000 VNĐ
Khuyến mại hết hạn Nhanh
Nội dung khuyến mại của Váy liền Eva - Thời trang Hàn Quốc Giá 340.000đ
Váy dáng bút chì vẫn đang là xu hướng thời trang được các bạn nữ yêu thích nhờ sự thoải mái và kiểu dáng nữ tính. Đặc biệt, kiểu dáng váy này thích hợp để đi làm, đi chơi hay tham gia các bữa tiệc hoặc đơn giản là chỉ dạo phố. Vì thế, hầu như bạn gái nào cũng đã xúng xính sở hữu 01 chiếc váy đa zi-năng này trong tủ đồ của mình. Hãy để nhanh.vn giúp bạn bổ sung thêm bộ sưu tập thời trang mùa thu đông năm nay với chiếc Váy liền bút chì Eva nữ tính - làm điệu thêm cho bạn gái nơi công sở, đi chơi hay đi dự tiệc, bạn nhé.
Được thiết kế đơn giản, kiểu dáng trẻ trung và lịch sự, thích hợp đến văn phòng làm việc, dự tiệc, liên hoan với bạn bè và cả khi dạo phố, rong chơi. Sẵn sàng cùng bạn khoe dáng ngọc ở mọi nơi. Chất liệu cao cấp, ôm lấy cơ thể, thấm hút mồ hôi tốt, co giãn bốn chiều, giúp bạn luôn cảm thấy thoải mái trong từng bước đi, cử chỉ.
Sản phẩm là sự kết hợp hài hòa giữa phong cách trẻ trung, cá tính đồng thời cũng rất dịu dàng, đảm bảo sẽ mang đến cho khách hàng một phong cách mới lạ mà không bị hòa lẫn giữa đám đông. Màu sắc tươi sáng, trẻ trung góp phần tôn lên nét xinh tươi, đáng yêu, sành điệu của các bạn trẻ.
Tên nhà cung cấp: Nhanh.vn
Địa chỉ: 51 Lê Đại Hành, P.Lê Đại Hành, Quận Hai Bà Trưng, Hà Nội
Mobile: 0934636165
Khuyến mại Thời trang khác
Khuyến mại khác danh mục
Lời nhắn
Xin chào ,
gửi bạn lời mời xem sản phẩm khuyến mại với thông tin như sau
Váy liền Eva - Thời trang Hàn Quốc Giá 340.000đ
Link xem sản phẩm: http://www.chonmua.com/khuyen-mai/vay-lien-eva-thoi-trang-han-quoc-gia.html
Email này được gửi đi từ website http://www.chonmua.com/khuyen-mai/
Chúc bạn có những giây phút thoải mái tại CHỌNMUA.COM
- Các sản phẩm người dùng mới đăng
-
khuyen mai 50% bán iphone 5 trắng (quốc tế) 32gb.............
Ngày đăng: 09:16 03/06/2015 0
-
Mỡ bò nước cao cấp (chuyên dùng cho ngành ôtô)
Ngày đăng: 07:41 28/05/2015 0
-
USB giá rẻ, bảo hành 2 năm
Ngày đăng: 07:35 28/05/2015 0
-
Wifi tenda tốc độ 150 Mbp.
Ngày đăng: 07:27 28/05/2015 0
-
Khuyến mại đồ bơi hot 2015: Set 3 bikini + váy chỉ 230K
Ngày đăng: 16:19 23/05/2015 0
-
Giấy bao tập – Mua 5 xấp tặng 2 xấp – Thiệp Hoa Mỹ Việt
Ngày đăng: 10:19 21/05/2015 0
-
TÚI XÁCH, BALO LAPTOp, VALI KÉO, VÍ NAM NỮ
Ngày đăng: 14:32 15/05/2015 0
-
Dụng cụ làm sushi 199000
Ngày đăng: 14:09 15/05/2015 1
-
Chuyên cung cấp tập 96trang, 200 trang giá rẻ
Ngày đăng: 12:49 15/05/2015 0
-
Đợt giảm giá lớn nhất trong năm
Ngày đăng: 08:28 15/05/2015 0
Viết bình luậnVáy liền Eva - Thời trang Hàn Quốc Giá 340.000đĐăng nhập/Đăng ký

markdown:
# Váy liền Eva - Thời trang Hàn Quốc Giá
* 340.000đ*
Giá bán: 340.000 VNĐ
[Chọn mua](/khuyen-mai/chuyen-trang?url=http%3A%2F%2Fnhanh.vn%2Fhang-thoi-trang%2Fp17278%2Fvay-lien-eva-v510.html%3Fpartner=Nhanh &deal_id=10468) **1**người chọn mua.
Khuyến mại hết hạn
Nhanh
## Nội dung khuyến mại của Váy liền Eva - Thời trang Hàn Quốc Giá 340.000đ
Váy dáng bút chì vẫn đang là xu hướng
[thời trang ](/khuyen-mai/khuyen-mai-thoi-trang/)được các bạn nữ yêu thích nhờ sự thoải mái và kiểu dáng nữ tính. Đặc biệt, kiểu dáng [ váy ](/khuyen-mai/khuyen-mai-vay/)này thích hợp để đi làm, đi chơi hay tham gia các bữa tiệc hoặc đơn giản là chỉ dạo phố. Vì thế, hầu như bạn gái nào cũng đã xúng xính sở hữu 01 chiếc ** váy ** đa zi-năng này trong tủ đồ của mình. Hãy để nhanh.vn giúp bạn bổ sung thêm bộ sưu tập **thời trang ** mùa thu đông năm nay với chiếc ** Váy ** liền bút chì Eva nữ tính - làm điệu thêm cho bạn gái nơi công sở, đi chơi hay đi dự tiệc, bạn nhé.
Được thiết kế đơn giản, kiểu dáng trẻ trung và lịch sự, thích hợp đến văn phòng làm việc, dự tiệc, liên hoan với bạn bè và cả khi dạo phố, rong chơi. Sẵn sàng cùng bạn khoe dáng ngọc ở mọi nơi. Chất liệu cao cấp, ôm lấy cơ thể, thấm hút mồ hôi tốt, co giãn bốn chiều, giúp bạn luôn cảm thấy thoải mái trong từng bước đi, cử chỉ.
Sản phẩm là sự kết hợp hài hòa giữa phong cách trẻ trung, cá tính đồng thời cũng rất dịu dàng, đảm bảo sẽ mang đến cho khách hàng một phong cách mới lạ mà không bị hòa lẫn giữa đám đông. Màu sắc tươi sáng, trẻ trung góp phần tôn lên nét xinh tươi, đáng yêu, sành điệu của các bạn trẻ.
[Xem thêm]
Tên nhà cung cấp:
**Nhanh.vn**
Địa chỉ: 51 Lê Đại Hành, P.Lê Đại Hành, Quận Hai Bà Trưng, Hà Nội
Mobile: 0934636165
## Khuyến mại Thời trang khác
![ Lượt xem](/images/deal/like-deal.png)
![ Bình luận](/images/deal/total-comment.png)
![ Lượt xem](/images/deal/like-deal.png)
![ Bình luận](/images/deal/total-comment.png)
![ Lượt xem](/images/deal/like-deal.png)
![ Bình luận](/images/deal/total-comment.png)
![ Lượt xem](/images/deal/like-deal.png)
![ Bình luận](/images/deal/total-comment.png)
![ Lượt xem](/images/deal/like-deal.png)
![ Bình luận](/images/deal/total-comment.png)
![ Lượt xem](/images/deal/like-deal.png)
![ Bình luận](/images/deal/total-comment.png)
![ Lượt xem](/images/deal/like-deal.png)
![ Bình luận](/images/deal/total-comment.png)
![ Lượt xem](/images/deal/like-deal.png)
![ Bình luận](/images/deal/total-comment.png)
## Khuyến mại khác danh mục
![ Lượt xem](/images/deal/like-deal.png)
![ Bình luận](/images/deal/total-comment.png)
![ Lượt xem](/images/deal/like-deal.png)
![ Bình luận](/images/deal/total-comment.png)
![ Lượt xem](/images/deal/like-deal.png)
![ Bình luận](/images/deal/total-comment.png)
![ Lượt xem](/images/deal/like-deal.png)
![ Bình luận](/images/deal/total-comment.png)
![ Lượt xem](/images/deal/like-deal.png)
![ Bình luận](/images/deal/total-comment.png)
![ Lượt xem](/images/deal/like-deal.png)
![ Bình luận](/images/deal/total-comment.png)
![ Lượt xem](/images/deal/like-deal.png)
![ Bình luận](/images/deal/total-comment.png)
![ Lượt xem](/images/deal/like-deal.png)
![ Bình luận](/images/deal/total-comment.png)
[Đóng [X]]
Lời nhắn
Xin chào ,
gửi bạn lời mời xem sản phẩm khuyến mại với thông tin như sau
**Váy liền Eva - Thời trang Hàn Quốc Giá 340.000đ**
Link xem sản phẩm:
[http://www.chonmua.com/khuyen-mai/vay-lien-eva-thoi-trang-han-quoc-gia.html](http://www.chonmua.com/khuyen-mai/vay-lien-eva-thoi-trang-han-quoc-gia.html)
Email này được gửi đi từ website
[http://www.chonmua.com/khuyen-mai/](http://www.chonmua.com/khuyen-mai/)
**Chúc bạn có những giây phút thoải mái tại CHỌNMUA.COM**
**Các sản phẩm người dùng mới đăng**
-
[khuyen mai 50% bán iphone 5 trắng (quốc tế) 32gb.............](/khuyen-mai/50-ban-iphone-5-trang-quoc-te-32gb.html)Ngày đăng: 09:16 03/06/2015
0
-
[Mỡ bò nước cao cấp (chuyên dùng cho ngành ôtô)](/khuyen-mai/mo-bo-nuoc-cao-cap-chuyen-dung-cho-nganh-oto.html)Ngày đăng: 07:41 28/05/2015
0
-
[USB giá rẻ, bảo hành 2 năm](/khuyen-mai/usb-gia-re-bao-hanh-2-nam-35a582a3.html)Ngày đăng: 07:35 28/05/2015
0
-
[Wifi tenda tốc độ 150 Mbp.](/khuyen-mai/usb-gia-re-bao-hanh-2-nam.html)Ngày đăng: 07:27 28/05/2015
0
-
[Khuyến mại đồ bơi hot 2015: Set 3 bikini + váy chỉ 230K](/khuyen-mai/do-boi-hot-2015-set-3-bikini-vay-chi-230k.html)Ngày đăng: 16:19 23/05/2015
0
-
[Giấy bao tập – Mua 5 xấp tặng 2 xấp – Thiệp Hoa Mỹ Việt](/khuyen-mai/giay-bao-tap-mua-5-xap-tang-2-xap-thiep-hoa-my-viet.html)Ngày đăng: 10:19 21/05/2015
0
-
[TÚI XÁCH, BALO LAPTOp, VALI KÉO, VÍ NAM NỮ](/khuyen-mai/tui-xach-balo-laptop-vali-keo-vi-nam-nu.html)Ngày đăng: 14:32 15/05/2015
0
-
[Dụng cụ làm sushi 199000](/khuyen-mai/dung-cu-lam-sushi-199000.html)Ngày đăng: 14:09 15/05/2015
1
-
[Chuyên cung cấp tập 96trang, 200 trang giá rẻ](/khuyen-mai/chuyen-cung-cap-tap-96trang-200-trang-gia-re.html)Ngày đăng: 12:49 15/05/2015
0
-
[Đợt giảm giá lớn nhất trong năm](/khuyen-mai/dot-giam-gia-lon-nhat-trong-nam.html)Ngày đăng: 08:28 15/05/2015
0
[Fanpage ChonMua](https://www.facebook.com/ChonMua)Nếu không vào được [Cách vào facebook](http://cachvaofacebook.com/cach-vao-facebook-moi-nhat.html)
## Viết bình luậnVáy liền Eva - Thời trang Hàn Quốc Giá 340.000đĐăng nhập/Đăng ký

WARC-Type: response

Content-Type: application/http; msgtype=response

WARC-Truncated: length

Content-Type: text/html; charset=utf-8

Connection: close

Set-Cookie: SESS7c9ab68dfc37d7ac51caf20961e9af3f=tl24a3a98d9al8t5j65e3uos01; expires=Sun, 20-Dec-2015 11:44:36 GMT; path=/; domain=.chonmua.com

Vary: Accept-Encoding

Content-Encoding: gzip

X-Cache-Status: MISS


text:
thấy link mà chưa test, anh em nào thử rùi báo lại dùm nhé
DownLoad-01-10
DownLoad-11-20
(quyển 01)
DownLoad-21-30
DownLoad-31-40
(quyển 02)
tong hop bai viet day va hoc tieng hoa du moi cap do
thấy link mà chưa test, anh em nào thử rùi báo lại dùm nhé

markdown:
thấy link mà chưa test, anh em nào thử rùi báo lại dùm nhé
[DownLoad-01-10](http://www.mediafire.com/?hywl0k5ymjm) [DownLoad-11-20](http://www.mediafire.com/?nyw1mwgwmmi)
(quyển 01)
[DownLoad-21-30](http://www.mediafire.com/?q1oudxfz4di) [DownLoad-31-40](http://www.mediafire.com/?nyenzjftom3)
(quyển 02)
tong hop bai viet day va hoc tieng hoa du moi cap do
thấy link mà chưa test, anh em nào thử rùi báo lại dùm nhé

Content-Type: text/html; charset=UTF-8

Cache-Control: private, max-age=0

X-Content-Type-Options: nosniff

X-XSS-Protection: 1; mode=block

Server: GSE


text:
Sáng ngày 16/11/2015 tại Đền thờ Liệt sĩ xã Xuân Trường, BTS GHPGVN huyện Xuân Lộc phối hợp cùng UBND, Công An Giao Thông huyện tổ chức Lễ Tưởng niệm các nạn nhân tử vong vì tai nạn giao thông.
Thơ Thiền trong thời kỳ văn học Lý-Trần đã thể hiện những tư tưởng hết sức độc đáo. Đó là mối quan hệ mật thiết giữa cõi Đạo và cõi Đời. Những bậc Thiền sư đã đem chất Đạo vào Đời và Đạo được nhìn dưới con mắt của Đời trần thế. Đọc thơ Thiền, người ta thấy ngời lên tư tưởng nhập thế của các vị Thiền sư. Đồng thời, qua mỗi vần thơ, người đọc còn thấy được bản lĩnh, ý chí về con đường đạt Đạo và thái độ sống lạc quan, tin tưởng của con người trong cuộc đời này.
Lý Nhân quả thật sự không phải đơn giản và chỉ cần cho người sơ cơ, mà tất cả chúng ta đều phải hiểu tường tận để có chánh kiến và lòng tin sâu sắc về đạo lý nầy. Có Chánh kiến nhân quả, chúng ta luôn thận trọng trong từng ý nghĩ, lời nói và việc làm để không tổn hại cho mình và cho người; chúng ta có đời sống xả kỷ, hòa điệu với vũ trụ vạn loại.
Một cậu bé 3 tuổi đột nhiên kể lại rành mạch việc mình bị sát hại ở kiếp trước như thế nào và còn nhận diện chính xác nơi chôn giấu xác chết, hung khí cũng như kẻ sát nhân.
Vậy thì xem ra yếu tố đầu tiên khiến tôi “giác ngộ” với đạo Phật là vì thấy giáo lý của Ngài quá chân thật. Theo tôi, chân thật chính là tiêu chuẩn đạo đức cao quý nhất của con người. Thiếu thành thật, xa rời sự thật, phản lại sự thật, che giấu sự thật thì mọi giá trị đều sụp đổ kể cả những gì gọi là linh thiêng, thánh thiện nhất trên cõi nhân gian này…
Sáng nay, 12-7 (27-5-Ất Mùi), kỳ thi tuyển sinh khóa XI của Học viện PGVN tại TP.HCM đã khai mạc tại Trường THPT Phú Nhuận (5 Hoàng Minh Giám, P.9, Q.Phú Nhuận, TP.HCM).
Văn hóa thể hiện qua nhiều lĩnh vực khác nhau, mỗi lĩnh vực thể hiện một trình độ văn hóa nhất định. Người cầm bút là một trong những loại văn hóa cao cấp, thể hiện tầm nhìn, nhận xét qua văn phong để định hướng độc giả theo quan điểm khách quan có chuẩn mực.
Nhận được tin báo từ TS Đoàn Ngọc Khôi, Phó Giám đốc Bảo tàng Tổng hợp tỉnh Quảng Ngãi, tôi được UBND tỉnh mời vào để nghiên cứu, đánh giá về chuyện “toàn thân xá lợi” của Hòa thượng Thích Minh Đức sau 26 năm viên tịch. Đồng thời phải tìm cách xử lý vì nhục thân của ngài đặt trong tháp đá bắt đầu có hiện tượng mối đùn… Thượng tọa Thích Hạnh Khương - trụ trì chùa Long Bửu, đội 11, thôn Xuân Vinh, xã Hành Đức, huyện Nghĩa Hành, tỉnh Quảng Ngãi, niềm nở tiếp chúng tôi và thuật lại câu chuyện.
Cùng nhau truyền bá thông điệp Phật đản – Vesak 2014 tổ chức tại Việt Nam
“Vui thay đức Phật ra đời
Cõi người an lạc – cõi trời hân hoan”
Rạng sáng 24/6, người nghệ sĩ, nhạc sĩ, nhà nghiên cứu của làng nhạc dân tộc Việt Nam qua đời tuổi ở 94 sau gần một tháng chữa trị tại bệnh viện.
Hôn lễ hoành tráng của cặp đôi vàng làng giải trí Việt có khoảng gần 1.000 khách mời và các món ăn toàn là đồ chay vì cô dâu chú rể không muốn sát sinh trong ngày vui.
Tổ Sư thường cảnh tỉnh “ tinh thần không chật, vật chất không hao, sự của lý là có, lý của nó là không” ý của Tổ muốn hàng xuất gia hãy vì lợi ích chung bước đầu khép mình trong khuôn khổ giới luật để thuần hoá thân tâm của mình vốn đã từ lâu như ngựa rong chơi ngoài đồng nội và chúng ta đã từng thọ học, hành lời Phật dạy “hãy thừa tự pháp Bảo hơn là thừa tự tài vật” đối với người con Phật, Pháp bảo chính là nguồn tài sản cao quí hơn mọi thứ tài sản trên đời
Sáng ngày 09/08/Ất Mùi (21/09/2015) tại tịnh xá Ngọc Bảo, thôn 10, xã Lộc Ngãi, huyện Bảo Lâm, tỉnh Lâm Đồng, long trọng tổ chức lễ Đặt đá trùng tu Ngôi Bảo điện.
Tánh không (tiếng Phạn là sunyata) là cả một sự huyền bí lớn lao, và có thể xem đây là khái niệm nòng cốt của toàn bộ giáo huấn Đại Thừa. Thật thế tánh không đã từng là đề tài cho không biết bao nhiêu tập luận giải.
khoa học gia và y giới tìm thấy một loại thuốc đặc biệt cho cơ thể và đời sống của con người, để gia tăng trí nhớ. Loại thuốc “đặc sản” nầy cũng giúp cho bộ não hoàn thiện hơn mà không tốn tiền, không bị phản ứng phụ. Loại thuốc ấy là Thiền.
Các tổ chức quốc tế đang nỗ lực để giúp đỡ hơn 4 triệu nạn nhân trong khu vực bị ảnh hưởng nặng nề nhất sau trận động đất. Hiện tại, đã có 12 tổ chức Phật giáo từ khắp nơi toàn thế giới đang tham gia công tác cứu trợ tại Nepal.
Dù cách xa Thành phố, nhưng đêm nay tại ngôi chùa Ấn Nghiêm bỗng náo nhiệt tiếng cười đùa của các em, những tràng vỗ tay thay cho tiếng đàn cùng những giọng hát hồn nhiên với sự hướng dẫn của nhạc sĩ Vũ Ngọc Toản bài Quà trung thu cho em

Server: Apache


text:
Trong ba bài viết mới đây của loạt bài này, tôi đã cho bạn thấy cách sử dụng khung công tác Javassist cho hoạt động lớp (classworking). Bây giờ tôi sẽ trình bày một cách tiếp cận rất khác để xử lí bytecode, đó là sử dụng Apache Byte Code Engineering Library (BCEL). BCEL hoạt động ở mức các lệnh JVM thực sự, không giống như giao diện mã nguồn được Javassist hỗ trợ. Cách tiếp cận mức thấp làm cho BCEL rất tốt khi bạn thực sự muốn kiểm soát mọi bước thực hiện chương trình, nhưng nó cũng làm cho hoạt động với BCEL phức tạp hơn nhiều so với sử dụng Javassist cho các trường hợp ở đó cả hai cùng làm việc.
Tôi sẽ bắt đầu bằng cách trình bày kiến trúc BCEL cơ bản, sau đó dành hầu hết bài viết này cho việc xây dựng lại ví dụ hoạt động lớp Javassist đầu tiên của tôi bằng BCEL. Tôi sẽ kết thúc bằng việc xem xét một số các công cụ có trong gói BCEL và một vài ứng dụng mà các nhà phát triển đã xây dựng ở trên BCEL.
Truy cập lớp BCEL
BCEL cung cấp cho bạn tất cả các khả năng cơ bản giống như Javassist kiểm tra, chỉnh sửa và tạo các lớp Java nhị phân. Sự khác biệt rõ ràng với BCEL là mọi thứ được thiết kế để làm việc ở mức ngôn ngữ chương trình dịch hợp ngữ (assembler) của JVM, hơn là giao diện mã nguồn do Javassist cung cấp. Có một số khác biệt sâu hơn dưới các vỏ bọc, gồm việc sử dụng hai hệ thống phân cấp riêng của các thành phần trong BCEL -- một cái kiểm tra mã hiện có và cái khác để tạo mã mới. Tôi sẽ giả định bạn quen với Javassist từ những bài viết trước trong loạt bài này (xem phần bên cạnh Đừng bỏ lỡ phần còn lại của loạt bài này). Vì vậy tôi sẽ tập trung vào những sự khác biệt có khả năng gây nhầm lẫn cho bạn khi bạn bắt đầu làm việc với BCEL.
Như với Javassist, các khía cạnh kiểm tra lớp của BCEL về cơ bản lặp lại những gì có sẵn trực tiếp trong nền tảng Java qua Reflection API. Điều trùng lắp này là cần thiết trong một bộ công cụ hoạt động lớp vì bạn thường không muốn nạp các lớp mà bạn đang làm việc với chúng cho đến sau khi chúng đã được thay đổi.
BCEL cung cấp một số định nghĩa không thay đổi cơ bản trong gói
org.apache.bcel, nhưng không kể những định
nghĩa này, tất cả các mã kiểm tra có liên quan nằm trong gói
org.apache.bcel.classfile. Điểm khởi đầu trong
gói này là lớp
JavaClass. Lớp này đóng vai trò
giống như trong việc truy cập thông tin lớp bằng cách sử dụng BCEL như lớp
java.lang.Class thực hiện khi dùng sự phản
chiếu của Java chuẩn.
JavaClass xác định các
phương thức để nhận được thông tin trường và phương thức cho lớp này, cũng
như thông tin theo cấu trúc về siêu lớp và các giao diện. Không giống như
java.lang.Class,
JavaClass cũng cung cấp quyền truy cập tới các thông tin nội
bộ cho lớp đó, gồm nhóm hằng số và các thuộc tính và biểu diễn lớp nhị
phân đầy đủ như một luồng byte.
Các cá thể
JavaClass thường được tạo bằng cách phân tích cú pháp lớp nhị
phân hiện có. BCEL cung cấp lớp
org.apache.bcel.Repositoryđể thực hiện phân tích cú pháp cho
bạn. Theo mặc định, BCEL phân tích cú pháp và lưu trữ nhanh các biểu diễn
của các lớp được tìm thấy trong đường dẫn lớp (classpath) JVM, nhận được
các biểu diễn lớp nhị phân thực sự từ một cá thể
org.apache.bcel.util.Repository (lưu ý sự khác biệt trong tên
gói). Hiện tại
org.apache.bcel.util.Repository
là một giao diện cho một nguồn biểu diễn lớp nhị phân. Bạn có thể thay thế
các đường dẫn khác để tìm kiếm các tệp lớp hoặc các cách truy cập thông
tin lớp khác, thay cho nguồn mặc định có sử dụng đường dẫn lớp.
Thay đổi các lớp
Bên cạnh việc truy cập kiểu-phản chiếu tới các thành phần
lớp,
org.apache.bcel.classfile.JavaClass cũng
cung cấp các phương thức để thay đổi lớp đó. Bạn có thể sử dụng những
phương thức này để thiết lập bất kỳ các thành phần lớp này với các giá trị
mới. Mặc dù, chúng thường không sử dụng trực tiếp, vì các lớp khác trong
gói đó không hỗ trợ cho việc xây dựng các phiên bản mới của các thành phần
theo bất kỳ cách hợp lý nào. Thay vào đó, có một tập riêng biệt đầy đủ các
lớp trong gói
org.apache.bcel.generic để cung
cấp phiên bản có thể chỉnh sửa được của các thành phần được các lớp
org.apache.bcel.classfile biểu diễn.
Cũng
như
org.apache.bcel.classfile.JavaClass là điểm
khởi đầu cho việc sử dụng BCEL để kiểm tra các lớp hiện có,
org.apache.bcel.generic.ClassGen là điểm bắt đầu
của bạn để tạo các lớp mới. Nó cũng thay đổi các lớp hiện tại -- để xử lý
trường hợp đó, có một hàm tạo lấy một cá thể
JavaClass và sử dụng nó để khởi tạo thông tin lớp
ClassGen. Một khi bạn đã hoàn tất các thay đổi
lớp của bạn, bạn có thể nhận được một sự biểu diễn lớp thích hợp từ cá thể
ClassGen bằng cách gọi một phương thức trả
về một
JavaClass, nó có thể lần lượt được
chuyển đổi sang biểu diễn lớp nhị phân.
Nói
lộn xộn quá phải không? Tôi nghĩ như vậy. Trong thực tế, việc quay lại và
tiến lên giữa hai gói này là một trong những khía cạnh làm việc bất tiện
nhất với BCEL. Các cấu trúc lớp sao chép lại hướng theo cách này, vì thế
nếu bạn đang làm việc với BCEL, thật bõ công để viết các lớp của trình bao
bọc (wrapper), mà nó có thể ẩn dấu một số các sự khác nhau này. Với bài
viết này, tôi sẽ chủ yếu làm việc với các lớp của gói
org.apache.bcel.generic và tránh sử dụng các trình bao bọc,
nhưng với bạn đây là một điều để ghi nhớ cho công việc riêng của
mình.
Ngoài
ClassGen, gói
org.apache.bcel.generic định nghĩa các lớp để
quản lý việc xây dựng các thành phần lớp khác nhau. Các lớp xây dựng này
gồm
ConstantPoolGen để xử lý nhóm hằng số
FieldGen và
MethodGen
cho các trường và các phương thức và
InstructionList để làm việc với các chuỗi của các lệnh JVM.
Cuối cùng, gói
org.apache.bcel.generic cũng
định nghĩa các lớp để biểu diễn mọi kiểu của các lệnh JVM. Bạn có thể trực
tiếp tạo các cá thể của các lớp này hoặc trong một số trường hợp bằng cách
sử dụng lớp của trình trợ giúp (helper)
org.apache.bcel.generic.InstructionFactory. Lợi thế của việc
sử dụng
InstructionFactory là nó xử lý các chi
tiết tạo sổ sách của việc xây dựng lệnh cho bạn (gồm cả việc thêm các mục
vào nhóm hằng số khi cần thiết cho các lệnh). Bạn sẽ thấy cách làm cho tất
cả các lớp này hoạt động cùng nhau trong phần tiếp theo.
Hoạt động lớp với BCEL
Đối với một ví dụ về việc áp dụng BCEL, tôi sẽ sử dụng cùng một nhiệm vụ mà tôi đã sử dụng như một ví dụ Javassist trong Phần 4 -- việc đo thời gian được dùng để thực hiện một phương thức. Tôi thậm chí sẽ sử dụng cùng một cách tiếp cận mà tôi đã sử dụng với Javassist: tôi sẽ tạo một bản sao của phương thức ban đầu có tính thời gian khi sử dụng một tên đã thay đổi, sau đó thay thế phần thân của phương thức ban đầu với mã bao bọc các tính toán đếm thời gian xung quanh một cuộc gọi đến phương thức đã đổi tên.
Chọn một vật thí nghiệm
Liệt kê 1 đưa ra một
phương thức ví dụ mà tôi sẽ sử dụng cho các mục đích giải thích: phương
thức
buildString của lớp
StringBuilder. Như tôi đã nói trong Phần
4, phương thức này xây dựng một
String
có độ dài yêu cầu bất kỳ bằng cách thực hiện chính xác những gì mà bất kỳ
chuyên gia hiệu năng Java nào khuyên bạn không nên làm -- nó liên
tục gắn thêm một ký tự vào cuối của một chuỗi để tạo một chuỗi dài hơn. Vì
các chuỗi không thay đổi được, nên cách tiếp cận này có nghĩa là một chuỗi
mới sẽ được xây dựng mỗi khi qua vòng lặp, với các dữ liệu được sao chép
từ chuỗi cũ và một ký tự được thêm vào cuối. Ảnh hưởng cuối cùng là phương
thức này phải chịu chi phí hoạt động càng ngày càng nhiều khi nó được sử
dụng để tạo các chuỗi dài hơn.
Liệt kê 1. Phương thức có tính giờ
public class StringBuilder { private String buildString(int length) { String result = ""; for (int i = 0; i < length; i++) { result += (char)(i%26 + 'a'); } return result; } public static void main(String[] argv) { StringBuilder inst = new StringBuilder(); for (int i = 0; i < argv.length; i++) { String result = inst.buildString(Integer.parseInt(argv[i])); System.out.println("Constructed string of length " + result.length()); } } }
Liệt kê 2 cho thấy mã nguồn tương đương với sự thay đổi hoạt động lớp mà tôi sẽ làm với BCEL. Ở đây phương thức của trình bao bọc (wrapper) chỉ lưu trữ thời gian hiện tại, sau đó gọi phương thức ban đầu đã đổi tên và in ra một thông báo thời gian trước khi trả về kết quả của cuộc gọi đến phương thức ban đầu.
Liệt kê 2. Tính thời gian đã thêm vào phương thức ban đầu
public class StringBuilder { private String buildString$impl(int length) { String result = ""; for (int i = 0; i < length; i++) { result += (char)(i%26 + 'a'); } return result; } private String buildString(int length) { long start = System.currentTimeMillis(); String result = buildString$impl(length); System.out.println("Call to buildString$impl took " + (System.currentTimeMillis()-start) + " ms."); return result; } public static void main(String[] argv) { StringBuilder inst = new StringBuilder(); for (int i = 0; i < argv.length; i++) { String result = inst.buildString(Integer.parseInt(argv[i])); System.out.println("Constructed string of length " + result.length()); } } }
Mã hóa phép chuyển đổi
Triển khai thực hiện mã để thêm việc tính thời gian phương
thức sử dụng các BCEL API mà tôi đã nêu ra trong phần Truy
cập lớp BCEL. Làm việc ở mức các lệnh JVM làm cho đoạn mã dài hơn
rất nhiều so với ví dụ Javassist trong Phần
4, do đó ở đây tôi sẽ duyệt qua nó từng đoạn một trước khi cung
cấp cho bạn việc thực hiện đầy đủ. Trong đoạn mã cuối cùng, tất cả các
đoạn này sẽ tạo nên chỉ một phương thức, một phương thức lấy một cặp tham
số:
cgen, một cá thể của lớp
org.apache.bcel.generic.ClassGen được khởi tạo
bằng các thông tin hiện có cho các lớp đang được thay đổi; và
method (phương thức), một cá thể
org.apache.bcel.classfile.Method cho phương thức
tôi sắp tính thời gian.
Liệt kê 3 có đoạn mã đầu tiên cho phương
thức chuyển đổi. Như bạn thấy từ các ý kiến, phần đầu tiên chỉ khởi tạo
các thành phần BCEL cơ bản mà tôi sắp sử dụng, gồm việc khởi tạo một cá
thể
org.apache.bcel.generic.MethodGen mới bằng
cách sử dụng các thông tin cho phương thức có tính giờ. Tôi thiết lập một
danh sách lệnh rỗng cho
MethodGen, để sau này
tôi sẽ điền vào đó với mã tính thời gian thực tế. Trong phần thứ hai, tôi
tạo một cá thể
org.apache.bcel.generic.MethodGen thứ hai từ phương thức ban
đầu, sau đó loại bỏ phương thức ban đầu khỏi lớp đó. Trong cá thể
MethodGen thứ hai này, tôi chỉ cần thay đổi tên
để sử dụng một hậu tố "$impl", sau đó gọi phương thức
getMethod() để chuyển đổi thông tin phương thức có thể thay
đổi được thành một dạng cố định như một cá thể
org.apache.bcel.classfile.Method. Sau đó tôi sử dụng cuộc gọi
addMethod() để thêm phương thức đã đổi tên
vào lớp đó.
Liệt kê 3. Thêm phương thức chặn
// set up the construction tools InstructionFactory ifact = new InstructionFactory(cgen); InstructionList ilist = new InstructionList(); ConstantPoolGen pgen = cgen.getConstantPool(); String cname = cgen.getClassName(); MethodGen wrapgen = new MethodGen(method, cname, pgen); wrapgen.setInstructionList(ilist); // rename a copy of the original method MethodGen methgen = new MethodGen(method, cname, pgen); cgen.removeMethod(method); String iname = methgen.getName() + "$impl"; methgen.setName(iname); cgen.addMethod(methgen.getMethod());
Liệt
kê 4 cung cấp các đoạn mã tiếp theo cho phương thức chuyển đổi. Ở đây phần
đầu tiên tính không gian bị chiếm bởi các tham số gọi phương thức trên
ngăn xếp. Vì đoạn này cần thiết để lưu trữ thời gian bắt đầu trên khung
ngăn xếp trước khi gọi phương thức bao bọc mà tôi cần phải biết có thể sử
dụng khoảng trống nào cho một biến cục bộ (lưu ý rằng tôi có thể sử dụng
việc xử lý biến cục bộ của BCEL để nhận được cùng tác dụng, nhưng với bài
viết này tôi thích một cách tiếp cận rõ ràng). Phần thứ hai của đoạn mã
này tạo cuộc gọi đến
java.lang.System.currentTimeMillis() để nhận được thời gian
bắt đầu, lưu nó vào khoảng trống của biến cục bộ đã được tính toán trong
khung ngăn xếp.
Có lẽ bạn tự hỏi tại sao tôi kiểm tra xem phương
thức đó có tĩnh hay không ở lúc bắt đầu tính toán kích thước tham số của
tôi, sau đó khởi tạo khe hở khung ngăn xếp là 0 nếu nó có (trái ngược với
một khe hở nếu nó không có). Cách tiếp cận này liên quan đến cách xử lý
các cuộc gọi phương thức ngôn ngữ Java. Đối với các phương thức không
tĩnh, tham số (ẩn) đầu tiên trên mỗi cuộc gọi là tham chiếu
này cho đối tượng đích, mà tôi cần phải tính đến
khi tính toán kích thước tập tham số đầy đủ trên khung ngăn xếp.
Liệt kê 4. Thiết lập cho cuộc gọi được bao bọc
// compute the size of the calling parameters Type[] types = methgen.getArgumentTypes(); int slot = methgen.isStatic() ? 0 : 1; for (int i = 0; i < types.length; i++) { slot += types[i].getSize(); } // save time prior to invocation ilist.append(ifact.createInvoke("java.lang.System", "currentTimeMillis", Type.LONG, Type.NO_ARGS, Constants.INVOKESTATIC)); ilist.append(InstructionFactory.createStore(Type.LONG, slot));
Liệt
kê 5 cho thấy đoạn mã để tạo cuộc gọi đến phương thức được bao bọc và lưu
kết quả (nếu có). Phần đầu tiên của đoạn mã này sẽ kiểm tra xem phương
thức này có tĩnh không. Nếu phương thức không tĩnh, tôi tạo mã để nạp tài
liệu tham khảo đối tượng
này cho ngăn xếp đó và
cũng có thể thiết lập kiểu gọi phương thức là ảo (
virtual) (chứ không phải tĩnh (
static)). Vòng lặp
for sau đó tạo
mã để sao chép tất cả các giá trị tham số cuộc gọi tới ngăn xếp đó, phương
thức
createInvoke() tạo cuộc gọi thực sự tới
phương thức được bao bọc và câu lệnh
ifcuối
cùng sẽ lưu giá trị kết quả đến vị trí biến cục bộ khác trong khung ngăn
xếp (nếu kiểu kết quả không phải là
rỗng ).
Liệt kê 5. Gọi phương thức được bao bọc
// call the wrapped method int offset = 0; short invoke = Constants.INVOKESTATIC; if (!methgen.isStatic()) { ilist.append(InstructionFactory.createLoad(Type.OBJECT, 0)); offset = 1; invoke = Constants.INVOKEVIRTUAL; } for (int i = 0; i < types.length; i++) { Type type = types[i]; ilist.append(InstructionFactory.createLoad(type, offset)); offset += type.getSize(); } Type result = methgen.getReturnType(); ilist.append(ifact.createInvoke(cname, iname, result, types, invoke)); // store result for return later if (result != Type.VOID) { ilist.append(InstructionFactory.createStore(result, slot+2)); }
Bây
giờ đi vào hoàn tất. Liệt kê 6 tạo mã để tính toán trên thực tế số mili
giây trôi qua kể từ thời gian bắt đầu và để in nó ra như thông báo có định
dạng hoàn chỉnh. Phần này sẽ rất phức tạp, nhưng hầu hết các hoạt động
thực sự chỉ là viết các thông báo kết quả riêng biệt. Nó không cung cấp
một số kiểu hoạt động mà tôi đã không sử dụng trong mã trước đó, gồm một
sự truy cập trường (đến
java.lang.System.out)
và một vài kiểu lệnh khác nhau. Hầu hết trong số các kiểu lệnh này nên dễ
hiểu nếu bạn nghĩ về JVM như là một bộ xử lý dựa vào-ngăn xếp, vì vậy tôi
sẽ không đi vào chi tiết tại đây.
Liệt kê 6. Tính và in ra thời gian đã sử dụng
// print time required for method call ilist.append(ifact.createFieldAccess("java.lang.System", "out", new ObjectType("java.io.PrintStream"), Constants.GETSTATIC)); ilist.append(InstructionConstants.DUP); ilist.append(InstructionConstants.DUP); String text = "Call to method " + methgen.getName() + " took "; ilist.append(new PUSH(pgen, text)); ilist.append(ifact.createInvoke("java.io.PrintStream", "print", Type.VOID, new Type[] { Type.STRING }, Constants.INVOKEVIRTUAL)); ilist.append(ifact.createInvoke("java.lang.System", "currentTimeMillis", Type.LONG, Type.NO_ARGS, Constants.INVOKESTATIC)); ilist.append(InstructionFactory.createLoad(Type.LONG, slot)); ilist.append(InstructionConstants.LSUB); ilist.append(ifact.createInvoke("java.io.PrintStream", "print", Type.VOID, new Type[] { Type.LONG }, Constants.INVOKEVIRTUAL)); ilist.append(new PUSH(pgen, " ms.")); ilist.append(ifact.createInvoke("java.io.PrintStream", "println", Type.VOID, new Type[] { Type.STRING }, Constants.INVOKEVIRTUAL));
Sau
khi mã thông báo tính thời gian được tạo, tất cả công việc để lại cho Liệt
kê 7 là hoàn thành mã phương thức của trình bao bọc (wrapper) với một sự
trả về giá trị kết quả đã lưu trữ (nếu có) từ cuộc gọi phương thức được
bao bọc, tiếp theo là hoàn thành phương thức của trình bao bọc đã được xây
dựng. Phần cuối cùng này liên quan đến một vài bước. Cuộc gọi đến
stripAttributes(true) chỉ ra lệnh cho BCEL không
tạo các thông tin gỡ rối cho phương thức được xây dựng, trong khi các cuộc
gọi
setMaxStack() và
setMaxLocals() tính toán và thiết lập thông tin về cách sử
dụng ngăn xếp cho phương thức này. Sau khi việc đó được thực hiện, tôi
thực sự có thể tạo phiên bản hoàn chỉnh của phương thức này và thêm nó vào
lớp.
Liệt kê 7. Hoàn thành trình bao bọc
// return result from wrapped method call if (result != Type.VOID) { ilist.append(InstructionFactory.createLoad(result, slot+2)); } ilist.append(InstructionFactory.createReturn(result)); // finalize the constructed method wrapgen.stripAttributes(true); wrapgen.setMaxStack(); wrapgen.setMaxLocals(); cgen.addMethod(wrapgen.getMethod()); ilist.dispose();
Mã đầy đủ
Liệt kê 8 cho
thấy đoạn mã hoàn chỉnh (được định dạng lại một chút để khớp với chiều
rộng), trong đó có một phương thức
main() để
chọn tên của tệp lớp và phương thức lớp được chuyển
đổi:
Liệt kê 8. Mã chuyển đổi xong
public class BCELTiming { private static void addWrapper(ClassGen cgen, Method method) { // set up the construction tools InstructionFactory ifact = new InstructionFactory(cgen); InstructionList ilist = new InstructionList(); ConstantPoolGen pgen = cgen.getConstantPool(); String cname = cgen.getClassName(); MethodGen wrapgen = new MethodGen(method, cname, pgen); wrapgen.setInstructionList(ilist); // rename a copy of the original method MethodGen methgen = new MethodGen(method, cname, pgen); cgen.removeMethod(method); String iname = methgen.getName() + "$impl"; methgen.setName(iname); cgen.addMethod(methgen.getMethod()); Type result = methgen.getReturnType(); // compute the size of the calling parameters Type[] types = methgen.getArgumentTypes(); int slot = methgen.isStatic() ? 0 : 1; for (int i = 0; i < types.length; i++) { slot += types[i].getSize(); } // save time prior to invocation ilist.append(ifact.createInvoke("java.lang.System", "currentTimeMillis", Type.LONG, Type.NO_ARGS, Constants.INVOKESTATIC)); ilist.append(InstructionFactory. createStore(Type.LONG, slot)); // call the wrapped method int offset = 0; short invoke = Constants.INVOKESTATIC; if (!methgen.isStatic()) { ilist.append(InstructionFactory. createLoad(Type.OBJECT, 0)); offset = 1; invoke = Constants.INVOKEVIRTUAL; } for (int i = 0; i < types.length; i++) { Type type = types[i]; ilist.append(InstructionFactory. createLoad(type, offset)); offset += type.getSize(); } ilist.append(ifact.createInvoke(cname, iname, result, types, invoke)); // store result for return later if (result != Type.VOID) { ilist.append(InstructionFactory. createStore(result, slot+2)); } // print time required for method call ilist.append(ifact.createFieldAccess("java.lang.System", "out", new ObjectType("java.io.PrintStream"), Constants.GETSTATIC)); ilist.append(InstructionConstants.DUP); ilist.append(InstructionConstants.DUP); String text = "Call to method " + methgen.getName() + " took "; ilist.append(new PUSH(pgen, text)); ilist.append(ifact.createInvoke("java.io.PrintStream", "print", Type.VOID, new Type[] { Type.STRING }, Constants.INVOKEVIRTUAL)); ilist.append(ifact.createInvoke("java.lang.System", "currentTimeMillis", Type.LONG, Type.NO_ARGS, Constants.INVOKESTATIC)); ilist.append(InstructionFactory. createLoad(Type.LONG, slot)); ilist.append(InstructionConstants.LSUB); ilist.append(ifact.createInvoke("java.io.PrintStream", "print", Type.VOID, new Type[] { Type.LONG }, Constants.INVOKEVIRTUAL)); ilist.append(new PUSH(pgen, " ms.")); ilist.append(ifact.createInvoke("java.io.PrintStream", "println", Type.VOID, new Type[] { Type.STRING }, Constants.INVOKEVIRTUAL)); // return result from wrapped method call if (result != Type.VOID) { ilist.append(InstructionFactory. createLoad(result, slot+2)); } ilist.append(InstructionFactory.createReturn(result)); // finalize the constructed method wrapgen.stripAttributes(true); wrapgen.setMaxStack(); wrapgen.setMaxLocals(); cgen.addMethod(wrapgen.getMethod()); ilist.dispose(); } public static void main(String[] argv) { if (argv.length == 2 && argv[0].endsWith(".class")) { try { JavaClass jclas = new ClassParser(argv[0]).parse(); ClassGen cgen = new ClassGen(jclas); Method[] methods = jclas.getMethods(); int index; for (index = 0; index < methods.length; index++) { if (methods[index].getName().equals(argv[1])) { break; } } if (index < methods.length) { addWrapper(cgen, methods[index]); FileOutputStream fos = new FileOutputStream(argv[0]); cgen.getJavaClass().dump(fos); fos.close(); } else { System.err.println("Method " + argv[1] + " not found in " + argv[0]); } } catch (IOException ex) { ex.printStackTrace(System.err); } } else { System.out.println ("Usage: BCELTiming class-file method-name"); } } }
Thực hiện một lượt
Liệt
kê 9 cho thấy các kết quả của lần đầu tiên chạy chương trình
StringBuilder ở dạng chưa thay đổi, sau đó chạy
chương trình
BCELTiming để thêm thông tin về
thời gian và cuối cùng là chạy chương trình
StringBuilder sau khi nó đã thay đổi. Bạn có thể thấy cách
StringBuilder bắt đầu thông báo các thời
gian thực hiện sau khi nó đã thay đổi và cách các thời gian tăng nhanh hơn
nhiều so với chiều dài của chuỗi được xây dựng do mã xây dựng chuỗi không
hiệu quả.
Liệt kê 9.Chạy các chương trình
[dennis]$ java StringBuilder 1000 2000 4000 8000 16000 Constructed string of length 1000 Constructed string of length 2000 Constructed string of length 4000 Constructed string of length 8000 Constructed string of length 16000 [dennis]$ java -cp bcel.jar:. BCELTiming StringBuilder.class buildString [dennis]$ java StringBuilder 1000 2000 4000 8000 16000 Call to method buildString$impl took 20 ms. Constructed string of length 1000 Call to method buildString$impl took 79 ms. Constructed string of length 2000 Call to method buildString$impl took 250 ms. Constructed string of length 4000 Call to method buildString$impl took 879 ms. Constructed string of length 8000 Call to method buildString$impl took 3875 ms. Constructed string of length 16000
Tóm tắt BCEL
Có nhiều thứ
với BCEL hơn chỉ là sự hỗ trợ hoạt động lớp cơ bản mà tôi đã thể hiện
trong bài viết này. Nó cũng gồm việc thực hiện trình kiểm tra đầy đủ để
đảm bảo rằng một lớp nhị phân là hợp lệ theo các đặc tả JVM (xem
org.apache.bcel.verifier.VerifierFactory), một
trình phân tách (disassembler) tạo một khung nhìn mức JVM được liên kết và
có bố cục đẹp của một lớp nhị phân và thậm chí một trình tạo chương trình
BCEL cung cấp mã nguồn cho một chương trình BCEL để xây dựng một lớp do
bạn cung cấp. (Lớp
org.apache.bcel.util.BCELifier không nằm trong Javadocs, do đó
hãy trông cậy vào mã nguồn với cách sử dụng. Tính năng này hấp dẫn, nhưng
kết quả có thể quá khó hiểu để dùng cho hầu hết các nhà phát triển).
Theo cách sử dụng BCEL riêng của mình, tôi đã phát hiện thấy trình
phân tách HTML đặc biệt có ích. Để tiến hành thử nghiệm nó, chỉ cần thực
hiện lớp
org.apache.bcel.util.Class2HTML với
đường dẫn đến tệp lớp mà bạn muốn tách ra như một đối số dòng lệnh. Nó sẽ
tạo các tệp HTML trong thư mục hiện tại. Ví dụ ở đây tôi sẽ phân tách lớp
StringBuilder mà tôi đã sử dụng cho ví dụ
tính thời gian của
tôi:
[dennis]$ java -cp bcel.jar org.apache.bcel.util.Class2HTML StringBuilder.class Processing StringBuilder.class...Done.
Hình
1 là một ảnh chụp màn hình của kết quả bố trí được trình phân tách tạo
nên. Trong ảnh chụp này khung lớn ở phía trên bên phải cho thấy sự phân
tách của phương thức trình bao bọc tính thời gian được thêm vào lớp
StringBuilder. Kết quả HTML đầy đủ có trong các
tệp tải về -- chỉ cần mở tệp StringBuilder.html trong một cửa sổ
trình duyệt nếu bạn muốn xem trực tiếp điều này".
Hình 1. Phân tách StringBuilder
Hiện nay, BCEL có lẽ là khung công tác được sử dụng rộng rãi nhất cho hoạt động lớp Java. Nó liệt kê một số dự án khác có sử dụng BCEL trên trang Web, gồm trình biên dịch Xalan XSLT, mở rộng AspectJ cho ngôn ngữ lập trình Java và triển khai thực hiện một số JDO. Nhiều dự án khác chưa được liệt kê cũng đang sử dụng BCEL, gồm dự án liên kết dữ liệu JiBX XML riêng của tôi. Tuy nhiên, một số các dự án được BCEL liệt kê từ đó đã chuyển sang thư viện khác, do vậy không nằm trong danh sách như là một hướng dẫn đúng sự thực để phổ biến của BCEL.
Những lợi thế lớn của BCEL là giấy phép Apache tiện lợi cho thương mại của nó và sự hỗ trợ mức lệnh JVM rộng rãi của nó. Các tính năng này, kết hợp với sự ổn định và tuổi thọ của nó, đã làm cho BCEL trở thành một sự lựa chọn rất phổ biến cho các ứng dụng hoạt động lớp. Nhưng BCEL dường như không phải là tất cả được thiết kế tốt cho cả về tốc độ lẫn tính dễ sử dụng. Javassist cung cấp một API thuận lợi hơn nhiều đối với hầu hết các mục đích, với tốc độ tương đương (hoặc thậm chí tốt hơn), ít nhất là trong các thử nghiệm đơn giản của tôi. Nếu dự án của bạn có thể tận dụng phần mềm có sử dụng Mozilla Public License (MPL) hoặc GNU Lesser General Public License (LGPL), thì Javassist có thể là một lựa chọn tốt hơn ngay bây giờ (nó có sẵn trong cả hai giấy phép này).
Phần tiếp theo
Bây giờ tôi đã giới thiệu cho bạn cả hai Javassist và BCEL, bài viết tiếp theo của tôi trong loạt bài này sẽ nghiên cứu một ứng dụng hầu như có ích về hoạt động lớp nhiều hơn những gì bạn đã nhìn thấy cho đến nay. Quay lại Phần 2, tôi đã giải thích sự phản chiếu gọi đến các phương thức chậm hơn nhiều so với các cuộc gọi trực tiếp như thế nào. Trong Phần 8, tôi sẽ chỉ ra cách bạn có thể sử dụng cả hai BCEL và Javassist để thay thế các cuộc gọi sự phản chiếu với mã được tạo ra động trong thời gian chạy -- với một sự cải tiến đáng kể về hiệu năng. Xem tiếp bài tháng tới về một trải nghiệm khác của Động lực học lập trình Java để tìm hiểu các chi tiết.
Tải về
Tài nguyên
- Nhận được tất cả các chi tiết về Thư viện kỹ thuật mã byte mã nguồn mở tại trang của dự án Apache.
- Tìm thêm về việc thiết kế Java bytecode trong "Java bytecode: Hiểu bytecode giúp bạn trở thành một lập trình viên tốt hơn" (developerWorks, 07.2001) của Peter Haggar.
- Để tham chiếu xuất sắc đến tập lệnh và kiến trúc JVM, hãy xem Bên trong máy ảo Java, của Bill Venners (Artima Software, Inc., 2004). Bạn có thể xem một vài chương ví dụ trực tuyến để lướt qua nó trước khi đặt mua.
- Bạn có thể mua hoặc xem Đặc tả máy ảo Java chính thức trực tuyến với nhận xét đáng tin cậy về tất cả các khía cạnh hoạt động JVM.
- AspectJ mở rộng ngôn ngữ Java với các tính năng theo hướng-khía cạnh, cách sử dụng BCEL liên kết mã vào các lớp được trình biên dịch tạo ra. Hãy tìm hiểu tất cả về nó ở trang dự án Eclipse.
- Đối với một số các dự án khác làm cho việc sử dụng BCEL, xem trình biên dịch Apache Xalan XSLTC cho các bảng định kiểu XSL, phần mở rộng Hansel JUnit để theo dõi các thông tin về mã trong các cuộc thử nghiệm và khung công tác JiBX for fast XML data binding.
- Bạn có muốn tìm hiểu thêm về lập trình hướng-khía cạnh không? Hãy thử "Cải thiện mô đun với việc lập trình theo hướng-khía cạnh" (developerWorks. 01. 2002) của Nicholas Lesiecki với một tổng quan về làm việc với ngôn ngữ AspectJ.
- Dự án Jikes mã nguồn mở cung cấp trình biên dịch phục tùng cao và rất nhanh cho ngôn ngữ lập trình Java. Hãy sử dụng nó để tạo bytecode của bạn theo kiểu cũ --từ mã nguồn Java.
- Tìm thêm hàng trăm tài nguyên công nghệ Java trên vùng công nghệ Java của developerWorks.
- Duyệt các sách về các chủ đề kỹ thuật này và khác.
Bình luận
-
Vùng dữ liệu trên developerWorks
Khám phá các bài viết xoay quanh lĩnh vực dữ liệu, Quản lý hệ thống thông tin
-
Vùng mã nguồn mở trên developerWorks
Xem các bài viết về HTML, CSS, JavaScript,...
-
Điện toán đám mây
Tìm hiểu về điện toán đám mây

markdown:
Trong ba bài viết mới đây của loạt bài này, tôi đã cho bạn thấy cách sử dụng khung công tác Javassist cho hoạt động lớp (classworking). Bây giờ tôi sẽ trình bày một cách tiếp cận rất khác để xử lí bytecode, đó là sử dụng Apache Byte Code Engineering Library (BCEL). BCEL hoạt động ở mức các lệnh JVM thực sự, không giống như giao diện mã nguồn được Javassist hỗ trợ. Cách tiếp cận mức thấp làm cho BCEL rất tốt khi bạn thực sự muốn kiểm soát mọi bước thực hiện chương trình, nhưng nó cũng làm cho hoạt động với BCEL phức tạp hơn nhiều so với sử dụng Javassist cho các trường hợp ở đó cả hai cùng làm việc.
Tôi sẽ bắt đầu bằng cách trình bày kiến trúc BCEL cơ bản, sau đó dành hầu hết bài viết này cho việc xây dựng lại ví dụ hoạt động lớp Javassist đầu tiên của tôi bằng BCEL. Tôi sẽ kết thúc bằng việc xem xét một số các công cụ có trong gói BCEL và một vài ứng dụng mà các nhà phát triển đã xây dựng ở trên BCEL.
## Truy cập lớp BCEL
BCEL cung cấp cho bạn tất cả các khả năng cơ bản giống
như Javassist kiểm tra, chỉnh sửa và tạo các lớp Java nhị phân. Sự khác
biệt rõ ràng với BCEL là mọi thứ được thiết kế để làm việc ở mức ngôn ngữ
chương trình dịch hợp ngữ (assembler) của JVM, hơn là giao diện mã nguồn
do Javassist cung cấp. Có một số khác biệt sâu hơn dưới các vỏ bọc, gồm
việc sử dụng hai hệ thống phân cấp riêng của các thành phần trong BCEL --
một cái kiểm tra mã hiện có và cái khác để tạo mã mới. Tôi sẽ giả định bạn
quen với Javassist từ những bài viết trước trong loạt bài này (xem phần
bên cạnh
[Đừng bỏ lỡ phần còn lại của loạt bài
này](#sidebar1)). Vì vậy tôi sẽ tập trung vào những sự khác biệt có khả năng gây
nhầm lẫn cho bạn khi bạn bắt đầu làm việc với BCEL.
Như với
Javassist, các khía cạnh kiểm tra lớp của BCEL về cơ bản lặp lại những gì
có sẵn trực tiếp trong nền tảng Java qua Reflection API. Điều trùng lắp
này là cần thiết trong một bộ công cụ hoạt động lớp vì bạn thường không
muốn nạp các lớp mà bạn đang làm việc với chúng cho đến
*sau khi*
chúng đã được thay đổi.
BCEL cung cấp một số định nghĩa không thay đổi cơ bản trong gói
org.apache.bcel, nhưng không kể những định
nghĩa này, tất cả các mã kiểm tra có liên quan nằm trong gói
org.apache.bcel.classfile. Điểm khởi đầu trong
gói này là lớp
JavaClass. Lớp này đóng vai trò
giống như trong việc truy cập thông tin lớp bằng cách sử dụng BCEL như lớp
java.lang.Class thực hiện khi dùng sự phản
chiếu của Java chuẩn.
JavaClass xác định các
phương thức để nhận được thông tin trường và phương thức cho lớp này, cũng
như thông tin theo cấu trúc về siêu lớp và các giao diện. Không giống như
java.lang.Class,
JavaClass cũng cung cấp quyền truy cập tới các thông tin nội
bộ cho lớp đó, gồm nhóm hằng số và các thuộc tính và biểu diễn lớp nhị
phân đầy đủ như một luồng byte.
Các cá thể
JavaClass thường được tạo bằng cách phân tích cú pháp lớp nhị
phân hiện có. BCEL cung cấp lớp
org.apache.bcel.Repositoryđể thực hiện phân tích cú pháp cho
bạn. Theo mặc định, BCEL phân tích cú pháp và lưu trữ nhanh các biểu diễn
của các lớp được tìm thấy trong đường dẫn lớp (classpath) JVM, nhận được
các biểu diễn lớp nhị phân thực sự từ một cá thể
org.apache.bcel.util.Repository (lưu ý sự khác biệt trong tên
gói). Hiện tại
org.apache.bcel.util.Repository
là một giao diện cho một nguồn biểu diễn lớp nhị phân. Bạn có thể thay thế
các đường dẫn khác để tìm kiếm các tệp lớp hoặc các cách truy cập thông
tin lớp khác, thay cho nguồn mặc định có sử dụng đường dẫn lớp.
### Thay đổi các lớp
Bên cạnh việc truy cập kiểu-phản chiếu tới các thành phần
lớp,
org.apache.bcel.classfile.JavaClass cũng
cung cấp các phương thức để thay đổi lớp đó. Bạn có thể sử dụng những
phương thức này để thiết lập bất kỳ các thành phần lớp này với các giá trị
mới. Mặc dù, chúng thường không sử dụng trực tiếp, vì các lớp khác trong
gói đó không hỗ trợ cho việc xây dựng các phiên bản mới của các thành phần
theo bất kỳ cách hợp lý nào. Thay vào đó, có một tập riêng biệt đầy đủ các
lớp trong gói
org.apache.bcel.generic để cung
cấp phiên bản có thể chỉnh sửa được của các thành phần được các lớp
org.apache.bcel.classfile biểu diễn.
Cũng
như
org.apache.bcel.classfile.JavaClass là điểm
khởi đầu cho việc sử dụng BCEL để kiểm tra các lớp hiện có,
org.apache.bcel.generic.ClassGen là điểm bắt đầu
của bạn để tạo các lớp mới. Nó cũng thay đổi các lớp hiện tại -- để xử lý
trường hợp đó, có một hàm tạo lấy một cá thể
JavaClass và sử dụng nó để khởi tạo thông tin lớp
ClassGen. Một khi bạn đã hoàn tất các thay đổi
lớp của bạn, bạn có thể nhận được một sự biểu diễn lớp thích hợp từ cá thể
ClassGen bằng cách gọi một phương thức trả
về một
JavaClass, nó có thể lần lượt được
chuyển đổi sang biểu diễn lớp nhị phân.
Nói
lộn xộn quá phải không? Tôi nghĩ như vậy. Trong thực tế, việc quay lại và
tiến lên giữa hai gói này là một trong những khía cạnh làm việc bất tiện
nhất với BCEL. Các cấu trúc lớp sao chép lại hướng theo cách này, vì thế
nếu bạn đang làm việc với BCEL, thật bõ công để viết các lớp của trình bao
bọc (wrapper), mà nó có thể ẩn dấu một số các sự khác nhau này. Với bài
viết này, tôi sẽ chủ yếu làm việc với các lớp của gói
org.apache.bcel.generic và tránh sử dụng các trình bao bọc,
nhưng với bạn đây là một điều để ghi nhớ cho công việc riêng của
mình.
Ngoài
ClassGen, gói
org.apache.bcel.generic định nghĩa các lớp để
quản lý việc xây dựng các thành phần lớp khác nhau. Các lớp xây dựng này
gồm
ConstantPoolGen để xử lý nhóm hằng số
FieldGen và
MethodGen
cho các trường và các phương thức và
InstructionList để làm việc với các chuỗi của các lệnh JVM.
Cuối cùng, gói
org.apache.bcel.generic cũng
định nghĩa các lớp để biểu diễn mọi kiểu của các lệnh JVM. Bạn có thể trực
tiếp tạo các cá thể của các lớp này hoặc trong một số trường hợp bằng cách
sử dụng lớp của trình trợ giúp (helper)
org.apache.bcel.generic.InstructionFactory. Lợi thế của việc
sử dụng
InstructionFactory là nó xử lý các chi
tiết tạo sổ sách của việc xây dựng lệnh cho bạn (gồm cả việc thêm các mục
vào nhóm hằng số khi cần thiết cho các lệnh). Bạn sẽ thấy cách làm cho tất
cả các lớp này hoạt động cùng nhau trong phần tiếp theo.
## Hoạt động lớp với BCEL
Đối với một ví dụ về việc áp dụng BCEL, tôi sẽ sử dụng cùng
một nhiệm vụ mà tôi đã sử dụng như một ví dụ Javassist trong
[Phần
4](http://www.ibm.com/developerworks/vn/library/j-dyn0916/) -- việc đo thời gian được dùng để thực hiện một phương thức. Tôi
thậm chí sẽ sử dụng cùng một cách tiếp cận mà tôi đã sử dụng với
Javassist: tôi sẽ tạo một bản sao của phương thức ban đầu có tính thời
gian khi sử dụng một tên đã thay đổi, sau đó thay thế phần thân của phương
thức ban đầu với mã bao bọc các tính toán đếm thời gian xung quanh một
cuộc gọi đến phương thức đã đổi tên.
### Chọn một vật thí nghiệm
Liệt kê 1 đưa ra một
phương thức ví dụ mà tôi sẽ sử dụng cho các mục đích giải thích: phương
thức
buildString của lớp
StringBuilder. Như tôi đã nói trong
[Phần
4](http://www.ibm.com/developerworks/vn/library/j-dyn0916/), phương thức này xây dựng một
String
có độ dài yêu cầu bất kỳ bằng cách thực hiện chính xác những gì mà bất kỳ
chuyên gia hiệu năng Java nào khuyên bạn
*không nên* làm -- nó liên
tục gắn thêm một ký tự vào cuối của một chuỗi để tạo một chuỗi dài hơn. Vì
các chuỗi không thay đổi được, nên cách tiếp cận này có nghĩa là một chuỗi
mới sẽ được xây dựng mỗi khi qua vòng lặp, với các dữ liệu được sao chép
từ chuỗi cũ và một ký tự được thêm vào cuối. Ảnh hưởng cuối cùng là phương
thức này phải chịu chi phí hoạt động càng ngày càng nhiều khi nó được sử
dụng để tạo các chuỗi dài hơn.
##### Liệt kê 1. Phương thức có tính giờ
public class StringBuilder { private String buildString(int length) { String result = ""; for (int i = 0; i < length; i++) { result += (char)(i%26 + 'a'); } return result; } public static void main(String[] argv) { StringBuilder inst = new StringBuilder(); for (int i = 0; i < argv.length; i++) { String result = inst.buildString(Integer.parseInt(argv[i])); System.out.println("Constructed string of length " + result.length()); } } }
Liệt kê 2 cho thấy mã nguồn tương đương với sự thay đổi hoạt động lớp mà tôi sẽ làm với BCEL. Ở đây phương thức của trình bao bọc (wrapper) chỉ lưu trữ thời gian hiện tại, sau đó gọi phương thức ban đầu đã đổi tên và in ra một thông báo thời gian trước khi trả về kết quả của cuộc gọi đến phương thức ban đầu.
##### Liệt kê 2. Tính thời gian đã thêm vào phương thức ban đầu
public class StringBuilder { private String buildString$impl(int length) { String result = ""; for (int i = 0; i < length; i++) { result += (char)(i%26 + 'a'); } return result; } private String buildString(int length) { long start = System.currentTimeMillis(); String result = buildString$impl(length); System.out.println("Call to buildString$impl took " + (System.currentTimeMillis()-start) + " ms."); return result; } public static void main(String[] argv) { StringBuilder inst = new StringBuilder(); for (int i = 0; i < argv.length; i++) { String result = inst.buildString(Integer.parseInt(argv[i])); System.out.println("Constructed string of length " + result.length()); } } }
### Mã hóa phép chuyển đổi
Triển khai thực hiện mã để thêm việc tính thời gian phương
thức sử dụng các BCEL API mà tôi đã nêu ra trong phần
[Truy
cập lớp BCEL](#h1). Làm việc ở mức các lệnh JVM làm cho đoạn mã dài hơn
rất nhiều so với ví dụ Javassist trong [Phần
4](http://www.ibm.com/developerworks/vn/library/j-dyn0916/), do đó ở đây tôi sẽ duyệt qua nó từng đoạn một trước khi cung
cấp cho bạn việc thực hiện đầy đủ. Trong đoạn mã cuối cùng, tất cả các
đoạn này sẽ tạo nên chỉ một phương thức, một phương thức lấy một cặp tham
số:
cgen, một cá thể của lớp
org.apache.bcel.generic.ClassGen được khởi tạo
bằng các thông tin hiện có cho các lớp đang được thay đổi; và
method (phương thức), một cá thể
org.apache.bcel.classfile.Method cho phương thức
tôi sắp tính thời gian.
Liệt kê 3 có đoạn mã đầu tiên cho phương
thức chuyển đổi. Như bạn thấy từ các ý kiến, phần đầu tiên chỉ khởi tạo
các thành phần BCEL cơ bản mà tôi sắp sử dụng, gồm việc khởi tạo một cá
thể
org.apache.bcel.generic.MethodGen mới bằng
cách sử dụng các thông tin cho phương thức có tính giờ. Tôi thiết lập một
danh sách lệnh rỗng cho
MethodGen, để sau này
tôi sẽ điền vào đó với mã tính thời gian thực tế. Trong phần thứ hai, tôi
tạo một cá thể
org.apache.bcel.generic.MethodGen thứ hai từ phương thức ban
đầu, sau đó loại bỏ phương thức ban đầu khỏi lớp đó. Trong cá thể
MethodGen thứ hai này, tôi chỉ cần thay đổi tên
để sử dụng một hậu tố "$impl", sau đó gọi phương thức
getMethod() để chuyển đổi thông tin phương thức có thể thay
đổi được thành một dạng cố định như một cá thể
org.apache.bcel.classfile.Method. Sau đó tôi sử dụng cuộc gọi
addMethod() để thêm phương thức đã đổi tên
vào lớp đó.
##### Liệt kê 3. Thêm phương thức chặn
// set up the construction tools InstructionFactory ifact = new InstructionFactory(cgen); InstructionList ilist = new InstructionList(); ConstantPoolGen pgen = cgen.getConstantPool(); String cname = cgen.getClassName(); MethodGen wrapgen = new MethodGen(method, cname, pgen); wrapgen.setInstructionList(ilist); // rename a copy of the original method MethodGen methgen = new MethodGen(method, cname, pgen); cgen.removeMethod(method); String iname = methgen.getName() + "$impl"; methgen.setName(iname); cgen.addMethod(methgen.getMethod());
Liệt
kê 4 cung cấp các đoạn mã tiếp theo cho phương thức chuyển đổi. Ở đây phần
đầu tiên tính không gian bị chiếm bởi các tham số gọi phương thức trên
ngăn xếp. Vì đoạn này cần thiết để lưu trữ thời gian bắt đầu trên khung
ngăn xếp trước khi gọi phương thức bao bọc mà tôi cần phải biết có thể sử
dụng khoảng trống nào cho một biến cục bộ (lưu ý rằng tôi có thể sử dụng
việc xử lý biến cục bộ của BCEL để nhận được cùng tác dụng, nhưng với bài
viết này tôi thích một cách tiếp cận rõ ràng). Phần thứ hai của đoạn mã
này tạo cuộc gọi đến
java.lang.System.currentTimeMillis() để nhận được thời gian
bắt đầu, lưu nó vào khoảng trống của biến cục bộ đã được tính toán trong
khung ngăn xếp.
Có lẽ bạn tự hỏi tại sao tôi kiểm tra xem phương
thức đó có tĩnh hay không ở lúc bắt đầu tính toán kích thước tham số của
tôi, sau đó khởi tạo khe hở khung ngăn xếp là 0 nếu nó có (trái ngược với
một khe hở nếu nó không có). Cách tiếp cận này liên quan đến cách xử lý
các cuộc gọi phương thức ngôn ngữ Java. Đối với các phương thức không
tĩnh, tham số (ẩn) đầu tiên trên mỗi cuộc gọi là tham chiếu
này cho đối tượng đích, mà tôi cần phải tính đến
khi tính toán kích thước tập tham số đầy đủ trên khung ngăn xếp.
##### Liệt kê 4. Thiết lập cho cuộc gọi được bao bọc
// compute the size of the calling parameters Type[] types = methgen.getArgumentTypes(); int slot = methgen.isStatic() ? 0 : 1; for (int i = 0; i < types.length; i++) { slot += types[i].getSize(); } // save time prior to invocation ilist.append(ifact.createInvoke("java.lang.System", "currentTimeMillis", Type.LONG, Type.NO_ARGS, Constants.INVOKESTATIC)); ilist.append(InstructionFactory.createStore(Type.LONG, slot));
Liệt
kê 5 cho thấy đoạn mã để tạo cuộc gọi đến phương thức được bao bọc và lưu
kết quả (nếu có). Phần đầu tiên của đoạn mã này sẽ kiểm tra xem phương
thức này có tĩnh không. Nếu phương thức không tĩnh, tôi tạo mã để nạp tài
liệu tham khảo đối tượng
này cho ngăn xếp đó và
cũng có thể thiết lập kiểu gọi phương thức là ảo (
virtual) (chứ không phải tĩnh (
static)). Vòng lặp
for sau đó tạo
mã để sao chép tất cả các giá trị tham số cuộc gọi tới ngăn xếp đó, phương
thức
createInvoke() tạo cuộc gọi thực sự tới
phương thức được bao bọc và câu lệnh
ifcuối
cùng sẽ lưu giá trị kết quả đến vị trí biến cục bộ khác trong khung ngăn
xếp (nếu kiểu kết quả không phải là
rỗng ).
##### Liệt kê 5. Gọi phương thức được bao bọc
// call the wrapped method int offset = 0; short invoke = Constants.INVOKESTATIC; if (!methgen.isStatic()) { ilist.append(InstructionFactory.createLoad(Type.OBJECT, 0)); offset = 1; invoke = Constants.INVOKEVIRTUAL; } for (int i = 0; i < types.length; i++) { Type type = types[i]; ilist.append(InstructionFactory.createLoad(type, offset)); offset += type.getSize(); } Type result = methgen.getReturnType(); ilist.append(ifact.createInvoke(cname, iname, result, types, invoke)); // store result for return later if (result != Type.VOID) { ilist.append(InstructionFactory.createStore(result, slot+2)); }
Bây
giờ đi vào hoàn tất. Liệt kê 6 tạo mã để tính toán trên thực tế số mili
giây trôi qua kể từ thời gian bắt đầu và để in nó ra như thông báo có định
dạng hoàn chỉnh. Phần này sẽ rất phức tạp, nhưng hầu hết các hoạt động
thực sự chỉ là viết các thông báo kết quả riêng biệt. Nó không cung cấp
một số kiểu hoạt động mà tôi đã không sử dụng trong mã trước đó, gồm một
sự truy cập trường (đến
java.lang.System.out)
và một vài kiểu lệnh khác nhau. Hầu hết trong số các kiểu lệnh này nên dễ
hiểu nếu bạn nghĩ về JVM như là một bộ xử lý dựa vào-ngăn xếp, vì vậy tôi
sẽ không đi vào chi tiết tại đây.
##### Liệt kê 6. Tính và in ra thời gian đã sử dụng
// print time required for method call ilist.append(ifact.createFieldAccess("java.lang.System", "out", new ObjectType("java.io.PrintStream"), Constants.GETSTATIC)); ilist.append(InstructionConstants.DUP); ilist.append(InstructionConstants.DUP); String text = "Call to method " + methgen.getName() + " took "; ilist.append(new PUSH(pgen, text)); ilist.append(ifact.createInvoke("java.io.PrintStream", "print", Type.VOID, new Type[] { Type.STRING }, Constants.INVOKEVIRTUAL)); ilist.append(ifact.createInvoke("java.lang.System", "currentTimeMillis", Type.LONG, Type.NO_ARGS, Constants.INVOKESTATIC)); ilist.append(InstructionFactory.createLoad(Type.LONG, slot)); ilist.append(InstructionConstants.LSUB); ilist.append(ifact.createInvoke("java.io.PrintStream", "print", Type.VOID, new Type[] { Type.LONG }, Constants.INVOKEVIRTUAL)); ilist.append(new PUSH(pgen, " ms.")); ilist.append(ifact.createInvoke("java.io.PrintStream", "println", Type.VOID, new Type[] { Type.STRING }, Constants.INVOKEVIRTUAL));
Sau
khi mã thông báo tính thời gian được tạo, tất cả công việc để lại cho Liệt
kê 7 là hoàn thành mã phương thức của trình bao bọc (wrapper) với một sự
trả về giá trị kết quả đã lưu trữ (nếu có) từ cuộc gọi phương thức được
bao bọc, tiếp theo là hoàn thành phương thức của trình bao bọc đã được xây
dựng. Phần cuối cùng này liên quan đến một vài bước. Cuộc gọi đến
stripAttributes(true) chỉ ra lệnh cho BCEL không
tạo các thông tin gỡ rối cho phương thức được xây dựng, trong khi các cuộc
gọi
setMaxStack() và
setMaxLocals() tính toán và thiết lập thông tin về cách sử
dụng ngăn xếp cho phương thức này. Sau khi việc đó được thực hiện, tôi
thực sự có thể tạo phiên bản hoàn chỉnh của phương thức này và thêm nó vào
lớp.
##### Liệt kê 7. Hoàn thành trình bao bọc
// return result from wrapped method call if (result != Type.VOID) { ilist.append(InstructionFactory.createLoad(result, slot+2)); } ilist.append(InstructionFactory.createReturn(result)); // finalize the constructed method wrapgen.stripAttributes(true); wrapgen.setMaxStack(); wrapgen.setMaxLocals(); cgen.addMethod(wrapgen.getMethod()); ilist.dispose();
### Mã đầy đủ
Liệt kê 8 cho
thấy đoạn mã hoàn chỉnh (được định dạng lại một chút để khớp với chiều
rộng), trong đó có một phương thức
main() để
chọn tên của tệp lớp và phương thức lớp được chuyển
đổi:
##### Liệt kê 8. Mã chuyển đổi xong
public class BCELTiming { private static void addWrapper(ClassGen cgen, Method method) { // set up the construction tools InstructionFactory ifact = new InstructionFactory(cgen); InstructionList ilist = new InstructionList(); ConstantPoolGen pgen = cgen.getConstantPool(); String cname = cgen.getClassName(); MethodGen wrapgen = new MethodGen(method, cname, pgen); wrapgen.setInstructionList(ilist); // rename a copy of the original method MethodGen methgen = new MethodGen(method, cname, pgen); cgen.removeMethod(method); String iname = methgen.getName() + "$impl"; methgen.setName(iname); cgen.addMethod(methgen.getMethod()); Type result = methgen.getReturnType(); // compute the size of the calling parameters Type[] types = methgen.getArgumentTypes(); int slot = methgen.isStatic() ? 0 : 1; for (int i = 0; i < types.length; i++) { slot += types[i].getSize(); } // save time prior to invocation ilist.append(ifact.createInvoke("java.lang.System", "currentTimeMillis", Type.LONG, Type.NO_ARGS, Constants.INVOKESTATIC)); ilist.append(InstructionFactory. createStore(Type.LONG, slot)); // call the wrapped method int offset = 0; short invoke = Constants.INVOKESTATIC; if (!methgen.isStatic()) { ilist.append(InstructionFactory. createLoad(Type.OBJECT, 0)); offset = 1; invoke = Constants.INVOKEVIRTUAL; } for (int i = 0; i < types.length; i++) { Type type = types[i]; ilist.append(InstructionFactory. createLoad(type, offset)); offset += type.getSize(); } ilist.append(ifact.createInvoke(cname, iname, result, types, invoke)); // store result for return later if (result != Type.VOID) { ilist.append(InstructionFactory. createStore(result, slot+2)); } // print time required for method call ilist.append(ifact.createFieldAccess("java.lang.System", "out", new ObjectType("java.io.PrintStream"), Constants.GETSTATIC)); ilist.append(InstructionConstants.DUP); ilist.append(InstructionConstants.DUP); String text = "Call to method " + methgen.getName() + " took "; ilist.append(new PUSH(pgen, text)); ilist.append(ifact.createInvoke("java.io.PrintStream", "print", Type.VOID, new Type[] { Type.STRING }, Constants.INVOKEVIRTUAL)); ilist.append(ifact.createInvoke("java.lang.System", "currentTimeMillis", Type.LONG, Type.NO_ARGS, Constants.INVOKESTATIC)); ilist.append(InstructionFactory. createLoad(Type.LONG, slot)); ilist.append(InstructionConstants.LSUB); ilist.append(ifact.createInvoke("java.io.PrintStream", "print", Type.VOID, new Type[] { Type.LONG }, Constants.INVOKEVIRTUAL)); ilist.append(new PUSH(pgen, " ms.")); ilist.append(ifact.createInvoke("java.io.PrintStream", "println", Type.VOID, new Type[] { Type.STRING }, Constants.INVOKEVIRTUAL)); // return result from wrapped method call if (result != Type.VOID) { ilist.append(InstructionFactory. createLoad(result, slot+2)); } ilist.append(InstructionFactory.createReturn(result)); // finalize the constructed method wrapgen.stripAttributes(true); wrapgen.setMaxStack(); wrapgen.setMaxLocals(); cgen.addMethod(wrapgen.getMethod()); ilist.dispose(); } public static void main(String[] argv) { if (argv.length == 2 && argv[0].endsWith(".class")) { try { JavaClass jclas = new ClassParser(argv[0]).parse(); ClassGen cgen = new ClassGen(jclas); Method[] methods = jclas.getMethods(); int index; for (index = 0; index < methods.length; index++) { if (methods[index].getName().equals(argv[1])) { break; } } if (index < methods.length) { addWrapper(cgen, methods[index]); FileOutputStream fos = new FileOutputStream(argv[0]); cgen.getJavaClass().dump(fos); fos.close(); } else { System.err.println("Method " + argv[1] + " not found in " + argv[0]); } } catch (IOException ex) { ex.printStackTrace(System.err); } } else { System.out.println ("Usage: BCELTiming class-file method-name"); } } }
### Thực hiện một lượt
Liệt
kê 9 cho thấy các kết quả của lần đầu tiên chạy chương trình
StringBuilder ở dạng chưa thay đổi, sau đó chạy
chương trình
BCELTiming để thêm thông tin về
thời gian và cuối cùng là chạy chương trình
StringBuilder sau khi nó đã thay đổi. Bạn có thể thấy cách
StringBuilder bắt đầu thông báo các thời
gian thực hiện sau khi nó đã thay đổi và cách các thời gian tăng nhanh hơn
nhiều so với chiều dài của chuỗi được xây dựng do mã xây dựng chuỗi không
hiệu quả.
##### Liệt kê 9.Chạy các chương trình
[dennis]$ java StringBuilder 1000 2000 4000 8000 16000 Constructed string of length 1000 Constructed string of length 2000 Constructed string of length 4000 Constructed string of length 8000 Constructed string of length 16000 [dennis]$ java -cp bcel.jar:. BCELTiming StringBuilder.class buildString [dennis]$ java StringBuilder 1000 2000 4000 8000 16000 Call to method buildString$impl took 20 ms. Constructed string of length 1000 Call to method buildString$impl took 79 ms. Constructed string of length 2000 Call to method buildString$impl took 250 ms. Constructed string of length 4000 Call to method buildString$impl took 879 ms. Constructed string of length 8000 Call to method buildString$impl took 3875 ms. Constructed string of length 16000
## Tóm tắt BCEL
Có nhiều thứ
với BCEL hơn chỉ là sự hỗ trợ hoạt động lớp cơ bản mà tôi đã thể hiện
trong bài viết này. Nó cũng gồm việc thực hiện trình kiểm tra đầy đủ để
đảm bảo rằng một lớp nhị phân là hợp lệ theo các đặc tả JVM (xem
org.apache.bcel.verifier.VerifierFactory), một
trình phân tách (disassembler) tạo một khung nhìn mức JVM được liên kết và
có bố cục đẹp của một lớp nhị phân và thậm chí một trình tạo chương trình
BCEL cung cấp mã nguồn cho một chương trình BCEL để xây dựng một lớp do
bạn cung cấp. (Lớp
org.apache.bcel.util.BCELifier không nằm trong Javadocs, do đó
hãy trông cậy vào mã nguồn với cách sử dụng. Tính năng này hấp dẫn, nhưng
kết quả có thể quá khó hiểu để dùng cho hầu hết các nhà phát triển).
Theo cách sử dụng BCEL riêng của mình, tôi đã phát hiện thấy trình
phân tách HTML đặc biệt có ích. Để tiến hành thử nghiệm nó, chỉ cần thực
hiện lớp
org.apache.bcel.util.Class2HTML với
đường dẫn đến tệp lớp mà bạn muốn tách ra như một đối số dòng lệnh. Nó sẽ
tạo các tệp HTML trong thư mục hiện tại. Ví dụ ở đây tôi sẽ phân tách lớp
StringBuilder mà tôi đã sử dụng cho ví dụ
tính thời gian của
tôi:
[dennis]$ java -cp bcel.jar org.apache.bcel.util.Class2HTML StringBuilder.class Processing StringBuilder.class...Done.
Hình
1 là một ảnh chụp màn hình của kết quả bố trí được trình phân tách tạo
nên. Trong ảnh chụp này khung lớn ở phía trên bên phải cho thấy sự phân
tách của phương thức trình bao bọc tính thời gian được thêm vào lớp
StringBuilder. Kết quả HTML đầy đủ có trong các
tệp tải về -- chỉ cần mở tệp
*StringBuilder.html* trong một cửa sổ
trình duyệt nếu bạn muốn xem trực tiếp điều này".
##### Hình 1. Phân tách StringBuilder
![ Phân tách StringBuilder](fig1.jpg)
Hiện nay, BCEL có lẽ là khung công tác được sử dụng rộng rãi nhất cho hoạt động lớp Java. Nó liệt kê một số dự án khác có sử dụng BCEL trên trang Web, gồm trình biên dịch Xalan XSLT, mở rộng AspectJ cho ngôn ngữ lập trình Java và triển khai thực hiện một số JDO. Nhiều dự án khác chưa được liệt kê cũng đang sử dụng BCEL, gồm dự án liên kết dữ liệu JiBX XML riêng của tôi. Tuy nhiên, một số các dự án được BCEL liệt kê từ đó đã chuyển sang thư viện khác, do vậy không nằm trong danh sách như là một hướng dẫn đúng sự thực để phổ biến của BCEL.
Những lợi thế lớn của BCEL là giấy phép Apache tiện lợi cho thương mại của nó và sự hỗ trợ mức lệnh JVM rộng rãi của nó. Các tính năng này, kết hợp với sự ổn định và tuổi thọ của nó, đã làm cho BCEL trở thành một sự lựa chọn rất phổ biến cho các ứng dụng hoạt động lớp. Nhưng BCEL dường như không phải là tất cả được thiết kế tốt cho cả về tốc độ lẫn tính dễ sử dụng. Javassist cung cấp một API thuận lợi hơn nhiều đối với hầu hết các mục đích, với tốc độ tương đương (hoặc thậm chí tốt hơn), ít nhất là trong các thử nghiệm đơn giản của tôi. Nếu dự án của bạn có thể tận dụng phần mềm có sử dụng Mozilla Public License (MPL) hoặc GNU Lesser General Public License (LGPL), thì Javassist có thể là một lựa chọn tốt hơn ngay bây giờ (nó có sẵn trong cả hai giấy phép này).
## Phần tiếp theo
Bây giờ tôi đã giới thiệu cho bạn cả hai Javassist và
BCEL, bài viết tiếp theo của tôi trong loạt bài này sẽ nghiên cứu một ứng
dụng hầu như có ích về hoạt động lớp nhiều hơn những gì bạn đã nhìn thấy
cho đến nay. Quay lại
[Phần
2](http://www.ibm.com/developerworks/vn/library/j-dyn0603/), tôi đã giải thích sự phản chiếu gọi đến các phương thức chậm
hơn nhiều so với các cuộc gọi trực tiếp như thế nào. Trong Phần 8, tôi sẽ
chỉ ra cách bạn có thể sử dụng cả hai BCEL và Javassist để thay thế các
cuộc gọi sự phản chiếu với mã được tạo ra động trong thời gian chạy -- với
một sự cải tiến đáng kể về hiệu năng. Xem tiếp bài tháng tới về một trải
nghiệm khác của *Động lực học lập trình Java* để tìm hiểu các chi
tiết.
## Tải về
|Mô tả||Tên||Kích thước|
|Mã ví dụ|
## Tài nguyên
- Nhận được tất cả các chi tiết về Thư viện kỹ thuật mã byte mã nguồn mở
tại
[trang của dự án Apache](http://jakarta.apache.org/bcel/index.html).
- Tìm thêm về việc thiết kế Java bytecode trong "
[Java bytecode: Hiểu bytecode giúp bạn trở thành một lập trình viên tốt hơn](http://www.ibm.com/developerworks/ibm/library/it-haggar_bytecode/?S_TACT=105AGY75)" ( *developerWorks*, 07.2001) của Peter Haggar.
- Để tham chiếu xuất sắc đến tập lệnh và kiến trúc JVM, hãy xem
*Bên trong máy ảo Java*, của Bill Venners (Artima Software, Inc., 2004). Bạn có thể [xem một vài chương ví dụ trực tuyến để](http://www.artima.com/insidejvm/ed2/)lướt qua nó trước khi đặt mua.
- Bạn có thể
[mua hoặc xem Đặc tả máy ảo Java chính thức trực tuyến](http://java.sun.com/docs/books/vmspec/index.html)với nhận xét đáng tin cậy về tất cả các khía cạnh hoạt động JVM.
- AspectJ mở rộng ngôn ngữ Java với các tính năng theo hướng-khía cạnh,
cách sử dụng BCEL liên kết mã vào các lớp được trình biên dịch tạo ra.
Hãy tìm hiểu tất cả về nó ở
[trang dự án Eclipse](http://eclipse.org/aspectj/).
- Đối với một số các dự án khác làm cho việc sử dụng BCEL, xem trình
biên dịch
[Apache Xalan XSLTC](http://xml.apache.org/xalan-j/xsltc_usage.html)cho các bảng định kiểu XSL, [phần mở rộng Hansel JUnit](http://hansel.sourceforge.net/)để theo dõi các thông tin về mã trong các cuộc thử nghiệm và [khung công tác JiBX](http://jibx.sourceforge.net/)for fast XML data binding.
- Bạn có muốn tìm hiểu thêm về lập trình hướng-khía cạnh không? Hãy thử
"
[Cải thiện mô đun với việc lập trình theo hướng-khía cạnh](http://www.ibm.com/developerworks/java/library/j-aspectj/?S_TACT=105AGY75)" ( *developerWorks*. 01. 2002) của Nicholas Lesiecki với một tổng quan về làm việc với ngôn ngữ AspectJ. [Dự án Jikes](http://jikes.sourceforge.net/)mã nguồn mở cung cấp trình biên dịch phục tùng cao và rất nhanh cho ngôn ngữ lập trình Java. Hãy sử dụng nó để tạo bytecode của bạn theo kiểu cũ --từ mã nguồn Java.
- Tìm thêm hàng trăm tài nguyên công nghệ Java trên
[vùng công nghệ Java](http://www.ibm.com/developerworks/java/?S_TACT=105AGY75)của [developerWorks](http://www.ibm.com/developerworks/java/?S_TACT=105AGY75). [Duyệt các sách](http://www.ibm.com/developerworks/apps/SendTo?bookstore=safari&S_TACT=105AGY75)về các chủ đề kỹ thuật này và khác.
## Bình luận
[Vùng dữ liệu trên developerWorks](http://www.ibm.com/developerworks/vn/views/data/libraryview.jsp)
Khám phá các bài viết xoay quanh lĩnh vực dữ liệu, Quản lý hệ thống thông tin
[Vùng mã nguồn mở trên developerWorks](http://www.ibm.com/developerworks/vn/views/opensource/libraryview.jsp)
Xem các bài viết về HTML, CSS, JavaScript,...
[Điện toán đám mây](http://www.ibm.com/developerworks/vn/views/cloud/libraryview.jsp)
Tìm hiểu về điện toán đám mây

Content-Language: en-US


text:
Các Trường Dạy Tiếng Bồ Đào Nha ở Lisbon, Bồ Đào Nha
Tìm trường Tiếng Bồ Đào Nha tốt nhất với mức giá hợp lý nhất. So sánh chất lượng, ý kiến đánh giá và các lời đề nghị về khóa học Tiếng Bồ Đào Nha cho người lớn và học sinh sinh viên tại Lisbon. Bạn cũng có thể so sánh các khóa học dành cho trẻ em và thanh thiếu niên ở Lisbon.
3 trường ngoại ngữ trong Lisbon, giá dao động từ 1210 € đến 1465 € cho khóa học Tiếng Bồ Đào Nha 2 tuần đã bao gồm chỗ ở.
Lisbon
Lisbon: Lisbon, thủ đô của Bồ Đào Nha còn được gọi là thành phố bẩy ngọn đồi, được coi là thành phố trắng, quê hương của các thủy thủ và người khám phá các biển, tương đương với bảy về mặt số. Nếu nhìn từ sông Tagus - một trong những nơi ngắm cảnh tuyệt vời nhất - Lisbon là một bức tranh theo trường phái ấn tượng với màu nâu vàng nhạt và màu tùng lam, chấm phá là các tháp nhà thờ và các mái vòm. Lisbon có khí hậu Đại Tây Dương cùng ảnh hưởng của Địa Trung Hải. Do những đặc điểm này, Lisbon có những ngày ngập tràn ánh nắng dù là vào mùa đông. Không tìm ra thông tin mình đang tìm kiếm? So sánh thêm Tiếng Bồ Đào Nha các trường ở Faro, Porto hoặc xem so sánh của tất cả các trường ở Bồ Đào Nha .
Trang web độc lập được nhiều người ghé thăm nhất trên thế giới nhận đăng ký đặt chỗ các khóa học ngoại ngữ , các buổi học Tiếng Bồ Đào Nha & các lớp học Tiếng Bồ Đào Nha & các chương trình học Tiếng Bồ Đào Nha ở nước ngoài tại các trường Tiếng Bồ Đào Nha ở Bồ Đào Nha.

markdown:
# Các Trường Dạy Tiếng Bồ Đào Nha ở Lisbon, Bồ Đào Nha
![](http://c0577872.cdn.cloudfiles.rackspacecloud.com/control_google_map.gif)
![Lisbon Lisbon](/vi/images/cities/lisbon_1.jpg)
Tìm trường Tiếng Bồ Đào Nha tốt nhất với mức giá hợp lý nhất. So sánh chất lượng, ý kiến đánh giá và các lời đề nghị về khóa học Tiếng Bồ Đào Nha cho người lớn và học sinh sinh viên tại Lisbon. Bạn cũng có thể so sánh
[các khóa học dành cho trẻ em và thanh thiếu niên ở Lisbon](/vi/cactruong-lisbon/tre-em).
3 trường ngoại ngữ trong Lisbon, giá dao động từ 1210 € đến 1465 € cho khóa học Tiếng Bồ Đào Nha 2 tuần đã bao gồm chỗ ở.
### Lisbon
| |Đánh giá tổng quát của học viên: | |![]()
**Chất lượng giảng dạy**: ![](http://c0577872.cdn.cloudfiles.rackspacecloud.com/15tr.gif)
**hoạt động xã hội và chương trình tham quan,**: ![](http://c0577872.cdn.cloudfiles.rackspacecloud.com/20tr.gif)
**Ví dụ về tính giá (2 tuần):**
|1210 €|| |![]()
|950 €||Group + Workshop (Các khóa học Tiếng Bồ Đào Nha - Các buổi học 25 một tuần)|
|+ 260 €||Ở Nhà Người Bản Xứ, Phòng đơn, Ăn sáng|
| |Đánh giá tổng quát của học viên: | |![]()
**Chất lượng giảng dạy**: ![](http://c0577872.cdn.cloudfiles.rackspacecloud.com/15tr.gif)
**hoạt động xã hội và chương trình tham quan,**: ![](http://c0577872.cdn.cloudfiles.rackspacecloud.com/25tr.gif)
**Ví dụ về tính giá (2 tuần):**
|1465 €|| |![]()
|1190 €||Super Intensive Course (Các khóa học Tiếng Bồ Đào Nha - Các buổi học 25 một tuần)|
|+ 275 €||Ở Nhà Người Bản Xứ - ngoài thành phố Lisbon (gần bờ biển), Phòng đơn, Không có bữa ăn|
**Lisbon:**Lisbon, thủ đô của Bồ Đào Nha còn được gọi là thành phố bẩy ngọn đồi, được coi là thành phố trắng, quê hương của các thủy thủ và người khám phá các biển, tương đương với bảy về mặt số. Nếu nhìn từ sông Tagus - một trong những nơi ngắm cảnh tuyệt vời nhất - Lisbon là một bức tranh theo trường phái ấn tượng với màu nâu vàng nhạt và màu tùng lam, chấm phá là các tháp nhà thờ và các mái vòm. Lisbon có khí hậu Đại Tây Dương cùng ảnh hưởng của Địa Trung Hải. Do những đặc điểm này, Lisbon có những ngày ngập tràn ánh nắng dù là vào mùa đông. **Không tìm ra thông tin mình đang tìm kiếm?**So sánh thêm [Tiếng Bồ Đào Nha các trường](/vi/portuguese-khoahoc)ở [Faro](/vi/cactruong-faro), [Porto](/vi/cactruong-porto)hoặc xem so sánh của tất cả [các trường ở Bồ Đào Nha](/vi/cactruong--portugal).
Trang web độc lập được nhiều người ghé thăm nhất trên thế giới nhận đăng ký đặt chỗ các khóa học ngoại ngữ , các buổi học Tiếng Bồ Đào Nha & các lớp học Tiếng Bồ Đào Nha & các chương trình học Tiếng Bồ Đào Nha ở nước ngoài tại các trường Tiếng Bồ Đào Nha ở Bồ Đào Nha.
![](http://c0577872.cdn.cloudfiles.rackspacecloud.com/transparent26.gif)

Set-Cookie: __cfduid=dd1f37f478971e23bc0f8d0fbc15dca2e1448612328; expires=Sat, 26-Nov-16 08:18:48 GMT; path=/; domain=.languagecourse.net; HttpOnly

Server: cloudflare-nginx


text:
Gian hàng bán
Rao vặt
Hỏi đáp
Thêm
Danh sách gian hàng
Tin tức từ Vatgia.com
Để kinh doanh Online thành công
Đánh giá sản phẩm
BaoKim.vn
MyTour.vn
Nhanh.vn
WebBNC.net
Ứng dụng
Thông báo
Hỗ trợ
Đăng ký
Đăng ký thành viên
Đăng ký gian hàng
Đăng nhập
Hoặc đăng nhập bằng
Nhớ mật khẩu
Quên mật khẩu?
Sản phẩm
Sản phẩm
Rao vặt
Hỏi đáp
Cửa hàng
Trang chủ
>
áo sơ mi nữ dáng dài
Bạn có muốn tìm thêm:
may phat dien mini
tủ lạnh mini
quạt mitsubishi
áo sơ mi nữ hàn quốc
áo phao bơi trẻ em
áo sơ mi nữ kiểu màu
điều hòa cây mini
áo sơ mi nữ voan dài tay
áo sơ mi kiểu
áo sơ mi nữ kiểu dài
áo sơ mi nữ form dài
áo sơ mi nữ tay dài
áo sơ mi nữ teen dài tay
áo sơ mi nữ voan dài
áo sơ mi nữ phọt dài
sơ-mi-nữ-dáng-dài
áo sơ mi nữ tay dài voan
áo sơ mi nữ ngắn dài
áo sơ mi nữ rộng dài
Tìm trong danh mục
Áo sơ mi nữ (6)
Danh mục
Thời trang nữ (6)
Quần áo nữ (6)
Áo sơ mi nữ (6)
Tất cả
Bán chạy
Mới cập nhật
Giá tăng dần
Giá giảm dần
-
Toàn quốc
Hà Nội
Hồ Chí Minh
Đang giảm giá
Gian hàng đảm bảo
Miễn phí vận chuyển
Gian hàng mới
6
sản phẩm với từ khóa “
áo sơ mi nữ dáng dài
”
165.000₫
Áo sơ mi dáng dài cách điệu thời trang DW101
banre
·
Hà Nội
25/11/2015 - 10:07
• Hãng sản xuất: Đang cập nhật
• Chất liệu: Vải
Xem nhanh
500.000₫
SM010 -Sơ mi dáng dài cổ đính đá
lilyshop
·
Hà Nội
12/11/2015 - 15:45
• Hãng sản xuất: Đang cập nhật
• Chất liệu: Vải
Xem nhanh
Liên hệ gian hàng...
Áo sơ mi dáng dài kẻ sọc Something Borrowed SO977AA73BFAVN
zalora
·
Hồ Chí Minh
19/11/2015 - 03:26
• Hãng sản xuất: Something Borrowed
• Chất liệu: Vải
Xem nhanh
Liên hệ gian hàng...
Áo sơ mi dáng dài kẻ sọc Something Borrowed SO977AA72BFBVN
zalora
·
Hồ Chí Minh
19/11/2015 - 03:11
• Hãng sản xuất: Something Borrowed
• Chất liệu: Vải
Xem nhanh
Liên hệ gian hàng...
Áo sơ mi dáng dài có túi Something Borrowed SO977AA68BFFVN
zalora
·
Hồ Chí Minh
19/11/2015 - 03:23
• Hãng sản xuất: Something Borrowed
• Chất liệu: Vải
Xem nhanh
Liên hệ gian hàng...
Áo sơ mi dáng dài có túi Something Borrowed SO977AA69BFEVN
zalora
·
Hồ Chí Minh
19/11/2015 - 03:23
• Hãng sản xuất: Something Borrowed
• Chất liệu: Vải
Xem nhanh
Tìm kiếm rao vặt
Xem tất cả
Áo sơ mi nữ 2 lớp vạt bầu
-
199.000 ₫
Đăng bởi:
storevivi
Cập nhật:
24/11/2015 - 22:18
Áo sơ mi nữ mang đến cho phái đẹp vẻ đẹp tự nhiên quý phái
-
176.000 ₫/ cái
Đăng bởi:
quynh8746
Cập nhật:
23/11/2015 - 09:23
Sơ mi nữ mang đến cho bạn vẻ đẹp tự nhiên , quý phái
-
195.000 ₫/ cái
Đăng bởi:
quynh8746
Cập nhật:
23/11/2015 - 09:14
Sơ Mi Nữ Cổ Giọt Nước
-
176.000 ₫
Đăng bởi:
ngoctho0854
Cập nhật:
20/11/2015 - 18:34
Áo Sơ Mi Nữ 3D Hoa Lan
-
210.000 ₫
Đăng bởi:
cong829602222
Cập nhật:
18/11/2015 - 01:27
Tìm kiếm hỏi đáp
Xem tất cả
Tư vấn mặc đẹp với áo sơ mi dáng dài ?
Đăng bởi:
lyhantu
Cập nhật:
27/03/2013 - 09:26
Cách mix đồ đẹp với áo sơ mi dáng dài?
Đăng bởi:
lyhantu
Cập nhật:
19/02/2014 - 09:29
Nhờ tư vấn trang phục công sở cho mẹ sau sinh, thấp, béo, eo bánh mỳ?
Đăng bởi:
daisonglong123
Cập nhật:
04/04/2014 - 10:00
Chọn áo sơ mi dáng dài năng động đón hè?
Đăng bởi:
hoangha84
Cập nhật:
16/04/2014 - 11:23
Những mẫu áo sơ mi dáng dài năng động đón hè 2014?
Đăng bởi:
lyhantu
Cập nhật:
23/04/2014 - 09:39
Hỗ trợ vận chuyển
Hỗ trợ thanh toán online
Chấp nhận thanh toán
Kết nối với chúng tôi
Điện thoại, viễn thông
Phụ kiện,thiết bị sửa chữa,...
Mobile
Thiết bị viễn thông
Dịch vụ viễn thông
Máy tính, linh kiện
Máy vi tính
Thiết bị cho máy tính
Máy văn phòng
Linh kiện, phụ kiện Laptop
Điện tử, điện máy
Thiết bị an ninh
Âm thanh
Đồ dùng trong bếp
Hình ảnh
Máy ảnh, máy quay
Thiết bị liên quan
Máy ảnh, máy quay
Dịch vụ chụp, rửa ảnh
Dịch vụ cho thuê máy ảnh, máy...
Ô tô, xe máy, xe đạp
Ô tô (Xe hơi)
Xe máy, phụ tùng xe máy
Phụ tùng ô tô
Đồ chơi ô tô
Công nghiệp, Xây dựng
Thiết bị điện, nước
Xây dựng
Vật tư, thiết bị công nghiệp
Cơ khí chế tạo
Thời trang, phụ kiện
Thời trang nữ
Đồng hồ đeo tay
Thời trang nam
Đồ trang sức
Mẹ & Bé
Đồ dùng cho trẻ
Đồ cho mẹ
Tắm gội, vệ sinh an toàn
Đồ cho bé khi ra ngoài
Sức khỏe, sắc đẹp
Y tế, sức khỏe
Nước hoa - Mỹ phẩm khác
Chăm sóc da mặt
Đồ trang điểm
Đồ dùng sinh hoạt
Đồ dùng nhà bếp, phòng ăn
Các loại đồ khác
Đồ dùng cá nhân
Đồ điện gia dụng
Nội thất, ngoại thất
Nội thất không gian, tổng hợp
Nội thất phòng ngủ
Nội thất văn phòng
Đèn trang trí, chiếu sáng
Sách, văn phòng, quà tặng
Hoa, quà tặng, đồ chơi
Sách
Thiết bị văn phòng
Thiết bị giáo dục
Thể thao
Golf (gôn)
Bóng đá
Tennis
Câu cá
Dịch vụ, giải trí, du lịch
Du lịch
Game, đồ chơi
In ấn
Dịch vụ vận tải, vận chuyển
Thực phẩm, đồ uống
Đồ uống
Bánh kẹo, mứt
Thực phẩm tươi sống
Thực phẩm chín, qua chế biến
Vatgia.com - Sàn giao dịch thương mại điện tử hàng đầu Việt Nam
Mua hàng trực tuyến mang lại sự tiện lợi, chủ động, lựa chọn đa dạng, với các dịch vụ hỗ trợ mua hàng, bán hàng, thanh toán an toàn, giao hàng chuyên nghiệp.
Với phương châm “Luôn đặt mình vào địa vị khách hàng và đối xử trên mong đợi của họ”, Vatgia.com không ngừng nỗ lực, cải tiến đáp ứng nhu cầu mua sắm cho người tiêu dùng.
Vatgia đảm bảo cung cấp đúng thông tin cho đúng người, đúng lúc, đảm bảo thanh toán trực tuyến bảo mật an toàn, áp dụng hình thức vận chuyển nhanh phù hợp.
Rao vặt
|
Hỏi đáp
|
Review - Đánh giá
|
Lưu trữ rao vặt
|
Quà tết
|
Việc làm
|
Dien thoai
|
Laptop
|
Mua ban oto
|
Xe may
|
iPhone 5
|
iPhone 5s
|
iPhone 6
|
iPhone 6 plus
|
iPhone 6s
|
iPhone 6s plus
|
iPhone 4
|
iPhone 4s
|
Điện thoại iphone
|
Galaxy s5
|
Galaxy s6
|
Áo khoác đẹp
|
Áo khoác da
|
Áo khoác nam
|
Giày nam
|
Vest nam
|
Đầm công sở
|
Áo khoác nữ
|
Giày cao gót
|
Bất động sản
|
Cho thue nha
|
Tìm việc
|
Máy lọc nước
|
Cách làm trắng da
|
Sim số đẹp
|
Đồ chơi laptop
|
Nối tóc
|
Thiết bị hội thảo
|
Gạo
|
Máy tập tình yêu
|
Đèn gương
|
Phim kiếm hiệp
|
Phần mềm quản lý trường học
|
Khung ảnh kỹ thuật số
|
Wax Tẩy lông
|
Máy gia công bằng tia lửa điện
Giới thiệu
|
Hướng dẫn
|
Quy chế hoạt động
|
Chính sách bảo mật thông tin
Công ty Cổ phần Vật Giá Việt Nam. Số GCNDT: 011032001615, cấp ngày 21/06/2012, nơi cấp: UBND thành phố Hà Nội
Trụ sở chính: Lê Đại Hành, Hai Bà Trưng, Hà Nội - Chi nhánh Hồ Chí Minh: Đường Lữ Gia, Phường 15, Quận 11, Hồ Chí Minh
Tài khoản
Giỏ hàng
Đã xem
Ứng dụng

Set-Cookie: u_nologin_id=2315077617; expires=Sun, 06-Mar-2016 08:16:00 GMT; path=/; httponly


text:
Video Categories
Today's Top 10 Phim
- Khi Yêu Đừng Nói Lời Chia Tay
- Tùy Đường Diễn Nghĩa
- Bước Nhảy Xì Tin
- Nghiêng Nghiêng Dòng Nước
- Thần Điêu Đại Hiệp 1995
- Tình Như Tia Nắng
- Tây Du Ký 1986
- Bức Màn Đen Tối
- Cô Gái Đồ Long 1986
- Nước Mắt Đại Trường Kim
Other Websites
- Tám Vui Lắm
- Hát Karaoke Online
- Bếp Nhà Ta
- Pháp Âm
- Vietnamese Dictionary
- Báo Đời
- Yêu Nhạc Vàng
- Anispace

markdown:
### Video Categories
### Today's Top 10 Phim
[Khi Yêu Đừng Nói Lời Chia Tay](/index.html?cid=6592&q=Khi+Yeu+Dung+Noi+Loi+Chia+Tay) [Tùy Đường Diễn Nghĩa](/index.html?cid=7152&q=Tuy+Duong+Dien+Nghia) [Bước Nhảy Xì Tin](/index.html?cid=2230&q=Buoc+Nhay+Xi+Tin+Con+Tiep) [Nghiêng Nghiêng Dòng Nước](/index.html?cid=8452&q=Nghieng+Nghieng+Dong+Nuoc) [Thần Điêu Đại Hiệp 1995](/index.html?cid=4659&q=Than+Dieu+Dai+Hiep+1995) [Tình Như Tia Nắng](/index.html?cid=5172&q=Tinh+Nhu+Tia+Nang) [Tây Du Ký 1986](/index.html?cid=5224&q=Tay+Du+Ky+1986) [Bức Màn Đen Tối](/index.html?cid=8142&q=Buc+Man+Den+Toi) [Cô Gái Đồ Long 1986](/index.html?cid=4512&q=Co+Gai+Do+Long+1986) [Nước Mắt Đại Trường Kim](/index.html?cid=960&q=Nuoc+Mat+Dai+Truong+Kim+Con+Tiep)
### Other Websites
[Tám Vui Lắm](http://www.tamvl.com/) [Hát Karaoke Online](http://www.timkaraoke.com/) [Bếp Nhà Ta](http://www.bepnhata.com/) [Pháp Âm](http://www.kinhphat.org/) [Vietnamese Dictionary](http://www.vndic.org) [Báo Đời](http://www.baodoi.com) [Yêu Nhạc Vàng](http://www.yeunhacvang.com) [Anispace](http://www.anispace.net)

Server: nginx

Cache-Control: max-age=0, no-cache


text:
Các tin khác
• Cáo phó bá quả phụ Nguyễn Bá Thuyên (24-11-2015)
• Cáo phó Kevin Nguyễn (13-11-2015)
• Cáo phó ông Phanxico Xavie Trương Đình Liệu (13-11-2015)
• Cáo Phó Cụ Bà Quả Phụ Nguyễn Văn Kim (31-10-2015)
• Cáo phó Nguyễn Đỗ Quốc Tuấn (23-10-2015)
• Khấp báo Linh Mục Phêrô Phan Phát Huồn (21-10-2015)
• Cáo phó ông Lê Tấn Hữu (10-10-2015)
• Cáo phó Martin Nguyễn Mạnh Hùng (14-09-2015)
• Cáo phó ông Nguyễn Hiền Việt (28-08-2015)
• Cáo phó ông Nguyễn Hiền Việt (27-08-2015)
Mới Nhất
Chùa Phổ Linh tổ chức mừng lễ Tạ Ơn
Năm điều những người mua sắm cần biết trong ngày Thứ Sáu Đen
Giáo Hoàng Francis đi xe Honda bình dân, mở cửa kính
Luật ân xá giấy phạt giao thông
Lệnh cắt giảm nước ở California sẽ kéo dài hết năm 2016
Nhiếp ảnh gia bỏ 6 năm để chụp bức ảnh hoàn hảo của chim bói cá
Nhẫn vàng 1,700 tuổi khắc hình thần tình yêu
Suýt thiêu trụi nhà vì làm theo hướng dẫn nấu ăn trên Facebook
Nổi Bật Nhất
Thổ bắn rơi chiến đấu cơ Nga, gây khó cho giải pháp ngưng chiến tại Syria
Cặp người Việt bị tố lường gạt một ông cụ lấy $3 triệu đi đánh bài
Hình ảnh SÀI GÒN biểu tình chống chuyến viếng thăm của chủ tịch Trung Cộng Tập Cận Bình
Đi bộ buổi sáng, thân phụ LM. Nguyễn Thanh Sơn bị đánh trọng thương
Cảnh sát tìm thân nhân trong vụ Nguyễn Hoàng giết chị trước khi tự sát
Báo Đức: Phùng Quang Thanh đã chết tại Pháp
Tưởng niệm Quốc Hận & kỷ niệm 12 năm thành lập Tượng Đài Chiến Sĩ Việt Mỹ
Cụ bà VN 122 tuổi được công nhận lớn tuổi nhất thế giới
Hàng trăm người leo rào để được tắm miễn phí
Nửa triệu người VN mong được sống với giới tính thật
Người Việt trồng cần sa trị giá $14 triệu trong kho hàng
46 thuyền nhân Việt bị Úc cưỡng bách hồi hương, mang về tận Vũng Tàu
1,000 người tham dự buổi giới thiệu phim Ride The Thunder
Đại Đức Nhuận Thư, trụ trì chùa Từ Nghiêm treo cổ tự tử
Hằng Trần được vinh danh là nữ dân cử gốc Á đầu tiên tại Georgia
Bỏ đời băng đảng, Huỳnh Phước mở nhà hàng Việt nhờ bà nội
Vụ án ma túy Bali Nine: phạm nhân Việt lên tiếng lần đầu từ trong tù Nam Dương
Thai phụ Tầu sinh con Mỹ
Vợ chồng họ Vương nghe tuyên án trong vụ tông chết thanh niên Mỹ
Hai người Việt, một Canada bị tố ăn cắp 1 tỉ địa chỉ email
Bảo hiểm Obamacare: Tôi nên mua ở mức nào?
Một vài vấn đề về Obamacare
Phở 86
Obamacare và hãng bảo hiểm
Mua bảo hiểm Obamacare ở đâu?
Obamacare tài trợ ra sao cho người mua bảo hiểm y tế cá nhân?
Một năm chỉ có một lần: Thời điểm mua bảo hiểm Obamacare
Dịch bệnh Robocalls và những tệ nạn (bài 3)
Dịch bệnh Robocalls và những tệ nạn (bài 2)
Dịch bệnh Robocalls và những tệ nạn
Mọi chi tiết liên quan hoặc đăng Quảng Cáo xin quý khách liên lạc về địa chỉ: 14891 Moran Street, Westminster, Ca 92683-5599, USA
Email: viendong@aol.com hoặc baoviendong@aol.com
Phone: (1)714-379-2851 hoặc Fax: 714-379-2853 - Chúng tôi nhận Credit Card và PayPal.
Powered by Kanovar. Copyright © 2013 by VIỄN ĐÔNG DAILY NEWS.

Cache-Control: private