㈠ 我在用java進行圖片壓縮時,遇到130MB 的圖片是報錯 , 像十幾MB時不會出錯,
Runtime.getRuntime().maxMemory(),查看一下jvm最大內存,若小了,可通過java參數來設置,如 java -Xmx1024m Test,將最大堆空間設為1024m
㈡ 請問在JAVA中如何刪除一個對象,也就是釋放一個對象所佔的內存.
前面是我自己理解的後面是復制的
java有自動垃圾回收機制
當垃圾收集器判斷已經沒有任何引用指向對象的時候,會調用對象的finalize方法來釋放對象占據的內存空間~
java中垃圾回收以前聽老師講好像是內存滿了他才去做一次整體垃圾回收,在回收垃圾的同時會調用finalize方法.你在構造一個類時可以構造一個類時覆蓋他的finalize方法以便於該類在被垃圾回收時執行一些代碼,比如釋放資源.
1.JVM的gc概述
gc即垃圾收集機制是指jvm用於釋放那些不再使用的對象所佔用的內存。java語言並不要求jvm有gc,也沒有規定gc如何工作。不過常用的jvm都有gc,而且大多數gc都使用類似的演算法管理內存和執行收集操作。
在充分理解了垃圾收集演算法和執行過程後,才能有效的優化它的性能。有些垃圾收集專用於特殊的應用程序。比如,實時應用程序主要是為了避免垃圾收集中斷,而大多數OLTP應用程序則注重整體效率。理解了應用程序的工作負荷和jvm支持的垃圾收集演算法,便可以進行優化配置垃圾收集器。
垃圾收集的目的在於清除不再使用的對象。gc通過確定對象是否被活動對象引用來確定是否收集該對象。gc首先要判斷該對象是否是時候可以收集。兩種常用的方法是引用計數和對象引用遍歷。
1.1.引用計數
引用計數存儲對特定對象的所有引用數,也就是說,當應用程序創建引用以及引用超出范圍時,jvm必須適當增減引用數。當某對象的引用數為0時,便可以進行垃圾收集。
1.2.對象引用遍歷
早期的jvm使用引用計數,現在大多數jvm採用對象引用遍歷。對象引用遍歷從一組對象開始,沿著整個對象圖上的每條鏈接,遞歸確定可到達(reachable)的對象。如果某對象不能從這些根對象的一個(至少一個)到達,則將它作為垃圾收集。在對象遍歷階段,gc必須記住哪些對象可以到達,以便刪除不可到達的對象,這稱為標記(marking)對象。
下一步,gc要刪除不可到達的對象。刪除時,有些gc只是簡單的掃描堆棧,刪除未標記的未標記的對象,並釋放它們的內存以生成新的對象,這叫做清除(sweeping)。這種方法的問題在於內存會分成好多小段,而它們不足以用於新的對象,但是組合起來卻很大。因此,許多gc可以重新組織內存中的對象,並進行壓縮(compact),形成可利用的空間。
為此,gc需要停止其他的活動活動。這種方法意味著所有與應用程序相關的工作停止,只有gc運行。結果,在響應期間增減了許多混雜請求。另外,更復雜的 gc不斷增加或同時運行以減少或者清除應用程序的中斷。有的gc使用單線程完成這項工作,有的則採用多線程以增加效率。
2.幾種垃圾回收機制
2.1.標記-清除收集器
這種收集器首先遍歷對象圖並標記可到達的對象,然後掃描堆棧以尋找未標記對象並釋放它們的內存。這種收集器一般使用單線程工作並停止其他操作。
2.2.標記-壓縮收集器
有時也叫標記-清除-壓縮收集器,與標記-清除收集器有相同的標記階段。在第二階段,則把標記對象復制到堆棧的新域中以便壓縮堆棧。這種收集器也停止其他操作。
2.3.復制收集器
這種收集器將堆棧分為兩個域,常稱為半空間。每次僅使用一半的空間,jvm生成的新對象則放在另一半空間中。gc運行時,它把可到達對象復制到另一半空間,從而壓縮了堆棧。這種方法適用於短生存期的對象,持續復制長生存期的對象則導致效率降低。
2.4.增量收集器
增量收集器把堆棧分為多個域,每次僅從一個域收集垃圾。這會造成較小的應用程序中斷。
2.5.分代收集器
這種收集器把堆棧分為兩個或多個域,用以存放不同壽命的對象。jvm生成的新對象一般放在其中的某個域中。過一段時間,繼續存在的對象將獲得使用期並轉入更長壽命的域中。分代收集器對不同的域使用不同的演算法以優化性能。
2.6.並發收集器
並發收集器與應用程序同時運行。這些收集器在某點上(比如壓縮時)一般都不得不停止其他操作以完成特定的任務,但是因為其他應用程序可進行其他的後台操作,所以中斷其他處理的實際時間大大降低。
2.7.並行收集器
並行收集器使用某種傳統的演算法並使用多線程並行的執行它們的工作。在多cpu機器上使用多線程技術可以顯著的提高java應用程序的可擴展性。
3.Sun HotSpot
1.4.1 JVM堆大小的調整
Sun HotSpot 1.4.1使用分代收集器,它把堆分為三個主要的域:新域、舊域以及永久域。Jvm生成的所有新對象放在新域中。一旦對象經歷了一定數量的垃圾收集循環後,便獲得使用期並進入舊域。在永久域中jvm則存儲class和method對象。就配置而言,永久域是一個獨立域並且不認為是堆的一部分。
下面介紹如何控制這些域的大小。可使用-Xms和-Xmx 控制整個堆的原始大小或最大值。
下面的命令是把初始大小設置為128M:
java –Xms128m
–Xmx256m為控制新域的大小,可使用-XX:NewRatio設置新域在堆中所佔的比例。
下面的命令把整個堆設置成128m,新域比率設置成3,即新域與舊域比例為1:3,新域為堆的1/4或32M:
java –Xms128m –Xmx128m
–XX:NewRatio =3可使用-XX:NewSize和-XX:MaxNewsize設置新域的初始值和最大值。
下面的命令把新域的初始值和最大值設置成64m:
java –Xms256m –Xmx256m –Xmn64m
永久域默認大小為4m。運行程序時,jvm會調整永久域的大小以滿足需要。每次調整時,jvm會對堆進行一次完全的垃圾收集。
使用-XX:MaxPerSize標志來增加永久域搭大小。在WebLogic Server應用程序載入較多類時,經常需要增加永久域的最大值。當jvm載入類時,永久域中的對象急劇增加,從而使jvm不斷調整永久域大小。為了避免調整,可使用-XX:PerSize標志設置初始值。
下面把永久域初始值設置成32m,最大值設置成64m。
java -Xms512m -Xmx512m -Xmn128m -XX:PermSize=32m -XX:MaxPermSize=64m
默認狀態下,HotSpot在新域中使用復制收集器。該域一般分為三個部分。第一部分為Eden,用於生成新的對象。另兩部分稱為救助空間,當Eden 充滿時,收集器停止應用程序,把所有可到達對象復制到當前的from救助空間,一旦當前的from救助空間充滿,收集器則把可到達對象復制到當前的to救助空間。From和to救助空間互換角色。維持活動的對象將在救助空間不斷復制,直到它們獲得使用期並轉入舊域。使用-XX:SurvivorRatio 可控制新域子空間的大小。
同NewRation一樣,SurvivorRation規定某救助域與Eden空間的比值。比如,以下命令把新域設置成64m,Eden佔32m,每個救助域各佔16m:
java -Xms256m -Xmx256m -Xmn64m -XX:SurvivorRation =2
如前所述,默認狀態下HotSpot對新域使用復制收集器,對舊域使用標記-清除-壓縮收集器。在新域中使用復制收集器有很多意義,因為應用程序生成的大部分對象是短壽命的。理想狀態下,所有過渡對象在移出Eden空間時將被收集。如果能夠這樣的話,並且移出Eden空間的對象是長壽命的,那麼理論上可以立即把它們移進舊域,避免在救助空間反復復制。但是,應用程序不能適合這種理想狀態,因為它們有一小部分中長壽命的對象。最好是保持這些中長壽命的對象並放在新域中,因為復制小部分的對象總比壓縮舊域廉價。為控制新域中對象的復制,可用-XX:TargetSurvivorRatio控制救助空間的比例(該值是設置救助空間的使用比例。如救助空間位1M,該值50表示可用500K)。該值是一個百分比,默認值是50。當較大的堆棧使用較低的 sruvivorratio時,應增加該值到80至90,以更好利用救助空間。用-XX:maxtenuring threshold可控制上限。
為放置所有的復制全部發生以及希望對象從eden擴展到舊域,可以把MaxTenuring Threshold設置成0。設置完成後,實際上就不再使用救助空間了,因此應把SurvivorRatio設成最大值以最大化Eden空間,設置如下:
java … -XX:MaxTenuringThreshold=0 –XX:SurvivorRatio=50000 …
4.BEA JRockit JVM的使用
Bea WebLogic 8.1使用的新的JVM用於Intel平台。在Bea安裝完畢的目錄下可以看到有一個類似於jrockit81sp1_141_03的文件夾。這就是 Bea新JVM所在目錄。不同於HotSpot把Java位元組碼編譯成本地碼,它預先編譯成類。JRockit還提供了更細致的功能用以觀察JVM的運行狀態,主要是獨立的GUI控制台(只能適用於使用Jrockit才能使用jrockit81sp1_141_03自帶的console監控一些cpu及 memory參數)或者WebLogic Server控制台。
Bea JRockit JVM支持4種垃圾收集器:
4.1.1.分代復制收集器
它與默認的分代收集器工作策略類似。對象在新域中分配,即JRockit文檔中的nursery。這種收集器最適合單cpu機上小型堆操作。
4.1.2.單空間並發收集器
該收集器使用完整堆,並與背景線程共同工作。盡管這種收集器可以消除中斷,但是收集器需花費較長的時間尋找死對象,而且處理應用程序時收集器經常運行。如果處理器不能應付應用程序產生的垃圾,它會中斷應用程序並關閉收集。
分代並發收集器這種收集器在護理域使用排它復制收集器,在舊域中則使用並發收集器。由於它比單空間共同發生收集器中斷頻繁,因此它需要較少的內存,應用程序的運行效率也較高,注意,過小的護理域可以導致大量的臨時對象被擴展到舊域中。這會造成收集器超負荷運作,甚至採用排它性工作方式完成收集。
4.1.3.並行收集器
該收集器也停止其他進程的工作,但使用多線程以加速收集進程。盡管它比其他的收集器易於引起長時間的中斷,但一般能更好的利用內存,程序效率也較高。
默認狀態下,JRockit使用分代並發收集器。要改變收集器,可使用-Xgc:,對應四個收集器分別為 gen,singlecon,gencon以及parallel。可使用-Xms和-Xmx設置堆的初始大小和最大值。要設置護理域,則使用- Xns:java –jrockit –Xms512m –Xmx512m –Xgc:gencon –Xns128m…盡管JRockit支持-verbose:gc開關,但它輸出的信息會因收集器的不同而異。JRockit還支持memory、 load和codegen的輸出。
注意 :如果 使用JRockit JVM的話還可以使用WLS自帶的console(C:\bea\jrockit81sp1_141_03\bin下)來監控一些數據,如cpu, memery等。要想能構監控必須在啟動服務時startWeblogic.cmd中加入-Xmanagement參數。
5.如何從JVM中獲取信息來進行調整
-verbose.gc開關可顯示gc的操作內容。打開它,可以顯示最忙和最空閑收集行為發生的時間、收集前後的內存大小、收集需要的時間等。打開- xx:+ printgcdetails開關,可以詳細了解gc中的變化。打開-XX: + PrintGCTimeStamps開關,可以了解這些垃圾收集發生的時間,自jvm啟動以後以秒計量。最後,通過-xx: + PrintHeapAtGC開關了解堆的更詳細的信息。為了了解新域的情況,可以通過-XX:=PrintTenuringDistribution開關了解獲得使用期的對象權。
6.Pdm系統JVM調整
6.1.伺服器:前提內存1G 單CPU
可通過如下參數進行調整:-server 啟用伺服器模式(如果CPU多,伺服器機建議使用此項)
-Xms,-Xmx一般設為同樣大小。 800m
-Xmn 是將NewSize與MaxNewSize設為一致。320m
-XX:PerSize 64m
-XX:NewSize 320m 此值設大可調大新對象區,減少Full GC次數
-XX:MaxNewSize 320m
-XX:NewRato NewSize設了可不設。
-XX: SurvivorRatio
-XX:userParNewGC 可用來設置並行收集
-XX:ParallelGCThreads 可用來增加並行度
-XXUseParallelGC 設置後可以使用並行清除收集器
-XX:UseAdaptiveSizePolicy 與上面一個聯合使用效果更好,利用它可以自動優化新域大小以及救助空間比值
6.2.客戶機:通過在JNLP文件中設置參數來調整客戶端JVM
JNLP中參數:initial-heap-size和max-heap-size
這可以在framework的RequestManager中生成JNLP文件時加入上述參數,但是這些值是要求根據客戶機的硬體狀態變化的(如客戶機的內存大小等)。建議這兩個參數值設為客戶機可用內存的60%(有待測試)。為了在動態生成JNLP時以上兩個參數值能夠隨客戶機不同而不同,可靠慮獲得客戶機系統信息並將這些嵌到首頁index.jsp中作為連接請求的參數。
在設置了上述參數後可以通過Visualgc 來觀察垃圾回收的一些參數狀態,再做相應的調整來改善性能。一般的標準是減少fullgc的次數,最好硬體支持使用並行垃圾回收(要求多CPU)。
㈢ 怎麼確定Java對象的大小
普通對象的結構如下,按64位機器的長度計算
1. 對象頭(_mark), 8個位元組
2. Oop指針,如果是32G內存以下的,默認開啟對象指針壓縮,4個位元組
3. 數據區
4.Padding(內存對齊),按照8的倍數對齊
數組對象結構是
1. 對象頭(_mark), 8個位元組
2. Oop指針,如果是32G內存以下的,默認開啟對象指針壓縮,4個位元組
3. 數組長度,4個位元組
4. 數據區
5. Padding(內存對齊),按照8的倍數對齊
清楚了對象在內存的基本布局後,咱們說兩種計算Java對象大小的方法
1. 通過java.lang.instrument.Instrumentation的getObjectSize(obj)直接獲取對象的大小
2. 通過sun.misc.Unsafe對象的objectFieldOffset(field)等方法結合反射來計算對象的大小
java.lang.instrument.Instrumentation.getObjectSize()的方式
先講講java.lang.instrument.Instrumentation.getObjectSize()的方式,這種方法得到的是Shallow Size,即遇到引用時,只計算引用的長度,不計算所引用的對象的實際大小。如果要計算所引用對象的實際大小,可以通過遞歸的方式去計算。
java.lang.instrument.Instrumentation的實例必須通過指定javaagent的方式才能獲得,具體的步驟如下:
1. 定義一個類,提供一個premain方法: public static void premain(String agentArgs, Instrumentation instP)
2. 創建META-INF/MANIFEST.MF文件,內容是指定PreMain的類是哪個: Premain-Class: sizeof.ObjectShallowSize
3. 把這個類打成jar,然後用java -javaagent XXXX.jar XXX.main的方式執行
有興趣可以看下博主的:http://blog.csdn.net/iter_zc/article/details/41822719
㈣ 如何用JAVA把內存里的二進制文件打包成ZIP包
Java代碼
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
class ZipTest {
// 壓縮
public static void zip(String zipFileName, String inputFile)
throws Exception {
File f = new File(inputFile);
ZipOutputStream out = new ZipOutputStream(new FileOutputStream(
zipFileName));
zip(out, f, f.getName());
System.out.println("zip done");
out.close();
}
private static void zip(ZipOutputStream out, File f, String base)
throws Exception {
out.putNextEntry(new ZipEntry(base));
FileInputStream in = new FileInputStream(f);
int b;
while ((b = in.read()) != -1)
out.write(b);
in.close();
}
public static void main(String[] args) {
try {
ZipTest t = new ZipTest();
t.zip("c:\\test.zip", "c:\\1.txt");
} catch (Exception e) {
e.printStackTrace(System.out);
}
}
}
㈤ 我在用java進行圖片壓縮時,遇到130MB 的圖片是報錯 , 像十幾MB時不會出錯,
Runtime.getRuntime().maxMemory(),查看一下jvm最大內存,若小了,可通過java參數來設置,如 java -Xmx1024m Test,將最大堆空間設為1024m
㈥ java編程:數據壓縮規則
你是不是問如何編寫一個程序來壓縮數據?如果你是想解決這個問題的話,繼續往下看,如果你只是想要應付考試的話就算了。
—— 分割線
JDK本身提供了數據壓縮的一個API
java.util.zip.Deflater.deflateBytes(byte[] b, int off, int len)
以下是我使用的一個例子,有點多,注釋看不懂可以問我,不知道怎麼用可以問我,其他的就算了。
/**
* threshold value for compress
*/
public static final int THRESHOLD = 1200;
/**
* Answer a byte array compressed in the DEFLATER format from bytes.
*
* @param bytes
* a byte array
* @return byte[] compressed bytes
* @throws IOException
*/
public static byte[] compress(byte[] bytes)
{
// Create the compressor with highest level of compression
Deflater compressor = new Deflater();
compressor.setLevel(Deflater.BEST_COMPRESSION);
// Give the compressor the data to compress
compressor.setInput(bytes);
compressor.finish();
// Create an expandable byte array to hold the compressed data.
// You cannot use an array that's the same size as the orginal because
// there is no guarantee that the compressed data will be smaller than
// the uncompressed data.
ByteArrayOutputStream bos = new ByteArrayOutputStream(bytes.length);
// Compress the data
byte[] buf = new byte[1024];
while (!compressor.finished())
{
int count = compressor.deflate(buf);
bos.write(buf, 0, count);
}
try
{
bos.close();
}
catch (IOException e)
{
}
// Get the compressed data
byte[] compressedData = bos.toByteArray();
return compressedData;
}
/**
* Answer a byte array that has been decompressed from the DEFLATER format.
*
* @param bytes
* a byte array
* @return byte[] compressed bytes
* @throws IOException
*/
public static byte[] uncompress(byte[] bytes)
{
// Create the decompressor and give it the data to compress
Inflater decompressor = new Inflater();
decompressor.setInput(bytes);
// Create an expandable byte array to hold the decompressed data
ByteArrayOutputStream bos = new ByteArrayOutputStream(bytes.length);
// Decompress the data
byte[] buf = new byte[1024];
while (!decompressor.finished())
{
try
{
int count = decompressor.inflate(buf);
bos.write(buf, 0, count);
}
catch (DataFormatException e)
{
}
}
try
{
bos.close();
}
catch (IOException e)
{
}
// Get the decompressed data
byte[] decompressedData = bos.toByteArray();
return decompressedData;
}
㈦ 高分求助!用Java實現對文件的zip壓縮解壓縮
java.util.zip 這個類是你需要的,具體怎麼操作就看JDK吧
㈧ Java基本數據類型
一、基本數據類型:
byte:Java中最小的數據類型,在內存中佔8位(bit),即1個位元組,取值范圍-128~127,默認值0
short:短整型,在內存中佔16位,即2個位元組,取值范圍-32768~32717,默認值0
int:整型,用於存儲整數,在內在中佔32位,即4個位元組,取值范圍-2147483648~2147483647,默認值0
long:長整型,在內存中佔64位,即8個位元組-2^63~2^63-1,默認值0L
float:浮點型,在內存中佔32位,即4個位元組,用於存儲帶小數點的數字(與double的區別在於float類型有效小數點只有6~7位),默認值0
double:雙精度浮點型,用於存儲帶有小數點的數字,在內存中佔64位,即8個位元組,默認值0
char:字元型,用於存儲單個字元,佔16位,即2個位元組,取值范圍0~65535,默認值為空
boolean:布爾類型,佔1個位元組,用於判斷真或假(僅有兩個值,即true、false),默認值false
二、Java數據類型基本概念:
數據類型在計算機語言裡面,是對內存位置的一個抽象表達方式,可以理解為針對內存的一種抽象的表達方式。接觸每種語言的時候,都會存在數據類型的認識,有復雜的、簡單的,各種數據類型都需要在學習初期去了解,Java是強類型語言,所以Java對於數據類型的規范會相對嚴格。數據類型是語言的抽象原子概念,可以說是語言中最基本的單元定義,在Java裡面,本質上講將數據類型分為兩種:基本類型和引用數據類型。
基本類型:簡單數據類型是不能簡化的、內置的數據類型、由編程語言本身定義,它表示了真實的數字、字元和整數。
引用數據類型:Java語言本身不支持C++中的結構(struct)或聯合(union)數據類型,它的復合數據類型一般都是通過類或介面進行構造,類提供了捆綁數據和方法的方式,同時可以針對程序外部進行信息隱藏。
三、Java中的數據類型與內存的關系
在Java中,每個存放數據的變數都是有類型的,如:
charch;floatx;inta,b,c;
ch是字元型的,就會分配到2個位元組內存。不同類型的變數在內存中分配的位元組數不同,同時存儲方式也是不同的。
所以給變數賦值前需要先確定變數的類型,確定了變數的類型,即確定了數據需分配內存空間的大小,數據在內存的存儲方式。
四、Java數據類型在內存中的存儲:
1)基本數據類型的存儲原理:所有的簡單數據類型不存在「引用」的概念,基本數據類型都是直接存儲在內存中的內存棧上的,數據本身的值就是存儲在棧空間裡面,而Java語言裡面八種數據類型是這種存儲模型;
2)引用類型的存儲原理:引用類型繼承於Object類(也是引用類型)都是按照Java裡面存儲對象的內存模型來進行數據存儲的,使用Java內存堆和內存棧來進行這種類型的數據存儲,簡單地講,昆明北大青鳥http://www.kmbdqn.cn/認為「引用」是存儲在有序的內存棧上的,而對象本身的值存儲在內存堆上的。
㈨ 一個Java對象到底佔多大內存
第一問中,integer,Double是可以准確知道大小的 java中int double(包裝類分別是Integer和Double,實際是一樣的)分別佔用的大小是4B 和8B 這里說的B,就是我們通常說的KB中的那個B,全稱是Byte。 1B = 8bit。 所以我們通常會說int是32位,有時候又4位元組 而String他是有char數組組成,一個長度為10的String,佔用的char就是10個,一個char是2B。 所以看String佔多少內存,需要知道String的長度 二問中:答案是可以的 摘自ObjectOutPutStream的API說明 FileOutputStream fos = new FileOutputStream("t.tmp"); ObjectOutputStream oos = new ObjectOutputStream(fos); oos.writeInt(12345); oos.writeObject("Today"); oos.writeObject(new Date()); oos.close();