2012-12-14 104 views
0

我正在嘗試爲不可信的java代碼編寫一個沙箱。
我用java編寫了沙盒。沙箱需要:
Java內存使用沙箱

  1. 不可信代碼的限制內存使用情況。如果不受信任的代碼使用的內存超過了指定的限制,則沙箱應終止程序。
  2. 如果不受信任的代碼沒有超過指定的限制,沙箱還應該能夠確定使用的「最大內存峯值」。

順便說一句,當我在這裏說的內存,它意味着堆+非堆內存。

我發現你可以設置內存閾值,並在內存池的一個超過閾值時收到通知。但這不是我想要的,因爲我想爲Heap +非堆內存設置限制。

我現在唯一的解決方案是輪詢每個小毫秒,使用getHeapMemoryUsage()和getNonHeapMemoryUsage()從MemoryMXBean獲取堆+非堆內存,並檢查它是否超出限制。

但我知道這個解決方案絕對不是太好(也有缺陷)。還有其他更好的解決方案嗎?

回答

4

單個JVM在所有線程中共享一個堆。你不能「沙箱」的內存。如果您希望爲每個應用程序管理內存,則必須運行單獨的進程。

現在,如果你想限制總體內存(堆+非堆),你可以調用系統函數setrlimit通過JNA(如果你運行的是Linux),或者也可以稱之爲ulimit運行Java程序之前。

要找出您的進程使用了​​多少內存,請從ManagementFactory.getOperatingSystemMXBean()獲取CommittedVirutalMemorySize屬性(但沒有getter)。

如果要通知即將發生的關機,請使用setrlimit/ulimit的軟限制。你的進程將定期獲得一個signal它已經超過了軟限制。如果您設置了硬限制並且超出了限制,則該過程將被終止。

編輯:增加了關於獲取內存大小和setrlimit信號的段落。

+0

好的,假設我設法使用JNA。我如何才能瞭解程序崩潰或沒有?而且,如果沒有崩潰,我如何獲得所用的最大內存? – Teddy

+0

爲了回答您的問題,我在回答中添加了一些內容。我沒有經驗試圖讓Java對信號做出反應,所以我不能說這對你是否適合。 – mikeslattery

0

如果沒有深奧的魔法,我不認爲這是可能的:重寫非信任代碼的字節碼或修改底層JVM來跟蹤內存使用情況。

作爲一個實驗,我已經實現了前者(重寫字節碼),以限制不可信代碼的內存分配(和指令消耗),使用-javaagents在重載時重寫了java類的字節碼並在每個內存分配前插入檢查。使用此功能,我們可以調用一個函數並將該函數(及其調用的任何內容)限制爲例如1024字節的內存分配和10000條指令,如果它超調,將導致拋出和異常。在勝負的工作代碼,請

https://github.com/lihaoyi/6858

TL;博士:這真是太難了。這不是不可能的,但如果你有最後期限會面,你不會嘗試做什麼,如果你真的有效,你可能會發布一份會議文件。